more serialization patches and error handling

This commit is contained in:
kn0sys 2024-09-09 04:18:48 -04:00
parent f8570df9a6
commit 4aa2dcfcba
No known key found for this signature in database
GPG key ID: 3BDB674C95F103FA
28 changed files with 773 additions and 555 deletions

1
Cargo.lock generated
View file

@ -1945,6 +1945,7 @@ dependencies = [
name = "neveko_gui"
version = "0.1.2-beta"
dependencies = [
"bincode",
"chrono",
"console_error_panic_hook",
"eframe",

View file

@ -17,6 +17,6 @@ use neveko_core::{
/// Creates user on initial login
#[get("/login/<signature>/<aid>/<uid>")]
pub async fn login(aid: String, uid: String, signature: String) -> Custom<Json<Authorization>> {
let m_auth: Authorization = auth::verify_login(aid, uid, signature).await;
Custom(Status::Created, Json(m_auth))
let m_auth = auth::verify_login(aid, uid, signature).await;
Custom(Status::Created, Json(m_auth.unwrap_or_default()))
}

View file

@ -15,7 +15,6 @@ use neveko_core::{
models::*,
proof,
reqres,
utils,
};
/// Add contact
@ -25,17 +24,18 @@ pub async fn add_contact(
_token: auth::BearerToken,
) -> Custom<Json<Contact>> {
let res_contact = contact::create(&req_contact).await;
if res_contact.cid.is_empty() {
let u_contact = res_contact.unwrap_or_default();
if u_contact.cid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Ok, Json(res_contact))
Custom(Status::Ok, Json(u_contact))
}
/// Return all contacts
#[get("/")]
pub async fn get_contacts(_token: auth::BearerToken) -> Custom<Json<Vec<Contact>>> {
let contacts = contact::find_all();
Custom(Status::Ok, Json(contacts))
Custom(Status::Ok, Json(contacts.unwrap_or_default()))
}
/// Delete a contact by CID
@ -44,9 +44,9 @@ pub async fn remove_contact(
contact: String,
_token: auth::BearerToken,
) -> Custom<Json<Vec<Contact>>> {
contact::delete(&contact);
let _ = contact::delete(&contact);
let contacts = contact::find_all();
Custom(Status::Ok, Json(contacts))
Custom(Status::Ok, Json(contacts.unwrap_or_default()))
}
/// prove payment

View file

@ -52,7 +52,7 @@ pub fn create(address: &String) -> Result<Authorization, MdbError> {
debug!("insert auth: {:?}", &new_auth);
let k = &new_auth.aid.as_bytes();
let v = bincode::serialize(&new_auth).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k, &v);
db::write_chunks(&s.env, &s.handle?, k, &v)?;
Ok(new_auth)
}
@ -83,11 +83,11 @@ fn update_expiration(f_auth: &Authorization, address: &String) -> Result<Authori
);
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes().to_vec());
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes().to_vec())?;
let k = u_auth.aid.as_bytes();
let v = bincode::serialize(&u_auth).unwrap_or_default();
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, k, &v);
db::write_chunks(&s.env, &s.handle?, k, &v)?;
Ok(u_auth)
}
@ -126,10 +126,10 @@ pub async fn verify_login(aid: String, uid: String, signature: String) -> Result
let u_auth = Authorization::update_uid(f_auth, String::from(&u.uid));
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes());
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_auth.aid.as_bytes())?;
let v = bincode::serialize(&u_auth).unwrap_or_default();
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, u_auth.aid.as_bytes(), &v);
db::write_chunks(&s.env, &s.handle?, u_auth.aid.as_bytes(), &v)?;
monero::close_wallet(&wallet_name, &wallet_password).await;
Ok(u_auth)
} else if !f_user.xmr_address.is_empty() {
@ -157,7 +157,7 @@ async fn verify_access(address: &String, signature: &String) -> Result<bool, Mdb
let now: i64 = chrono::offset::Utc::now().timestamp();
let expiration = get_auth_expiration();
if now > f_auth.created + expiration {
update_expiration(&f_auth, address);
update_expiration(&f_auth, address)?;
return Ok(false);
}
}
@ -291,7 +291,7 @@ mod tests {
fn cleanup(k: &String) -> Result<(), MdbError>{
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?;
Ok(())
}

View file

@ -1,12 +1,7 @@
//! contact operations module
use crate::{
db,
i2p,
models::*,
monero,
reqres,
utils,
db, error::NevekoError, i2p, models::*, monero, reqres, utils
};
use kn0sys_lmdb_rs::MdbError;
use log::{
@ -43,7 +38,7 @@ pub async fn create(c: &Json<Contact>) -> Result<Contact, MdbError> {
let s = db::DatabaseEnvironment::open()?;
let k = &new_contact.cid;
let v = bincode::serialize(&new_contact).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v);
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v)?;
// in order to retrieve all contact, write keys to with cl
let list_key = crate::CONTACT_LIST_DB_KEY;
let str_lk = String::from(list_key);
@ -60,7 +55,7 @@ pub async fn create(c: &Json<Contact>) -> Result<Contact, MdbError> {
contact_list, list_key
);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), &contact_list.as_bytes());
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), &contact_list.as_bytes())?;
Ok(new_contact)
}
@ -78,14 +73,14 @@ pub fn find(cid: &String) -> Result<Contact, MdbError> {
}
/// Contact lookup
pub fn find_by_i2p_address(i2p_address: &String) -> Result<Contact , MdbError> {
let contacts = find_all()?;
pub fn find_by_i2p_address(i2p_address: &String) -> Result<Contact , NevekoError> {
let contacts = find_all().map_err(|_| NevekoError::Database(MdbError::NotFound))?;
for c in contacts {
if c.i2p_address == *i2p_address {
return Ok(c);
}
}
Err(MdbError::NotFound)
Err(NevekoError::Database(MdbError::NotFound))
}
/// Contact deletion
@ -98,7 +93,7 @@ pub fn delete(cid: &String) -> Result<(), MdbError> {
return Err(MdbError::NotFound);
}
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, cid.as_bytes());
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, cid.as_bytes())?;
Ok(())
}
@ -142,10 +137,11 @@ async fn validate_contact(j: &Json<Contact>) -> bool {
}
/// Send our information
pub async fn share() -> Result<Contact, MdbError> {
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &NEVEKO_VENDOR_ENABLED.as_bytes().to_vec())?;
pub async fn share() -> Result<Contact, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &NEVEKO_VENDOR_ENABLED.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let is_vendor = str_r == NEVEKO_VENDOR_MODE_ON;
let wallet_name = String::from(crate::APP_NAME);
@ -235,7 +231,7 @@ mod tests {
fn cleanup(k: &String) {
let s = db::DatabaseEnvironment::open();
db::DatabaseEnvironment::delete(&s.env, &s.handle, k);
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle, k)?;
}
#[test]

View file

@ -19,7 +19,11 @@ const CHUNK_SIZE_MEMORY_RATIO: f32 = MAP_SIZE_MEMORY_RATIO * 0.01;
///
/// By default the database will be written to /home/user/.neveko/{ENV}/lmdb
pub struct DatabaseEnvironment {
/// Represents LMDB Environment.
//TODO(n12n): cache the DB handle to avoid multiple open ops
pub env: Environment,
/// DB handle.
// TODO(n12n): cache the DB handle to avoid multiple open ops
pub handle: Result<DbHandle, MdbError>,
}
@ -199,7 +203,7 @@ mod tests {
let actual = DatabaseEnvironment::read(&db.env, &db.handle?, &Vec::from(k));
assert_eq!(expected.to_vec(), actual?);
let db = DatabaseEnvironment::open()?;
let _ = DatabaseEnvironment::delete(&db.env, &db.handle?, &Vec::from(k));
let _ = DatabaseEnvironment::delete(&db.env, &db.handle?, &Vec::from(k))?;
Ok(())
}
}

View file

@ -28,7 +28,7 @@ pub fn create(d: Json<Dispute>) -> Result<Dispute, MdbError> {
let s = db::DatabaseEnvironment::open()?;
let k = &d.did;
let v = bincode::serialize(&new_dispute).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v);
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &v)?;
// in order to retrieve all orders, write keys to with dl
let list_key = crate::DISPUTE_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open()?;
@ -43,7 +43,7 @@ pub fn create(d: Json<Dispute>) -> Result<Dispute, MdbError> {
dispute_list, list_key
);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), dispute_list.as_bytes());
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), dispute_list.as_bytes())?;
// restart the dispute aut-settle thread
let cleared = is_dispute_clear(s_r);
if !cleared {
@ -130,7 +130,7 @@ pub async fn settle_dispute() -> Result<(), MdbError>{
// index was created but cleared
info!("terminating dispute auto-settle thread");
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, list_key.as_bytes());
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, list_key.as_bytes())?;
return Ok(());
}
for d in d_vec {
@ -150,7 +150,7 @@ pub async fn settle_dispute() -> Result<(), MdbError>{
return Ok(());
}
// remove the dispute from the db
remove_from_auto_settle(dispute.did);
remove_from_auto_settle(dispute.did)?;
}
}
}
@ -198,7 +198,7 @@ fn remove_from_auto_settle(did: String) -> Result<(), MdbError> {
dispute_list, list_key
);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), dispute_list.as_bytes());
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), dispute_list.as_bytes())?;
Ok(())
}

View file

@ -11,6 +11,7 @@ pub enum NevekoError {
Dispute,
I2P,
J4I2PRS,
Message,
MoneroRpc,
MoneroDaemon,
Nasr,

View file

@ -21,6 +21,8 @@ use std::{
time::Duration,
};
const TODO: &str = "test";
#[derive(Debug, Deserialize, Serialize)]
pub struct HttpProxyStatus {
pub open: bool,
@ -99,8 +101,7 @@ async fn find_tunnels() {
/// proxy tunnel, etc. Logs proxy status every 10 minutes.
pub async fn start() {
info!("starting i2p-zero");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let path = TODO;
let output = Command::new(format!("{}/router/bin/i2p-zero", path)).spawn();
match output {
Ok(child) => debug!("{:?}", child.stdout),
@ -125,8 +126,7 @@ pub async fn start() {
/// Create an i2p tunnel for the NEVEKO application
fn create_tunnel() {
info!("creating tunnel");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let path = TODO;
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args([
"server.create",
@ -141,8 +141,7 @@ fn create_tunnel() {
/// Create an i2p tunnel for the monero wallet socks proxy
fn create_socks_proxy_tunnel() {
info!("creating monerod socks proxy tunnel");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let path = TODO;
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args(["socks.create", &get_i2p_socks_proxy_port().to_string()])
.spawn()
@ -154,7 +153,7 @@ fn create_socks_proxy_tunnel() {
fn create_anon_inbound_tunnel() {
info!("creating monerod anon inbound proxy tunnel");
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let path = TODO;
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args([
"server.create",
@ -186,8 +185,7 @@ fn get_i2p_socks_proxy_port() -> String {
/// Create the http proxy if it doesn't exist
fn create_http_proxy() {
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let path = TODO;
info!("creating http proxy");
let port = get_i2p_proxy_port();
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
@ -242,8 +240,7 @@ pub fn get_destination(port: Option<u16>) -> String {
/// Ping the i2p-zero http proxy `tunnel-control http.state <port>`
pub async fn check_connection() -> ProxyStatus {
let args = args::Args::parse();
let path = args.i2p_zero_dir;
let path = TODO;
let port = get_i2p_proxy_port();
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
.args(["http.state", &port])

View file

@ -3,14 +3,16 @@
use crate::{
contact,
db,
error::NevekoError,
i2p,
models::*,
monero,
neveko25519,
order,
reqres,
utils,
utils
};
use kn0sys_lmdb_rs::MdbError;
use log::{
debug,
error,
@ -44,7 +46,7 @@ struct MultisigMessageData {
}
/// Create a new message
pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Message {
pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Result<Message, NevekoError> {
let rnd = utils::generate_rnd();
let mut f_mid: String = format!("{}{}", crate::MESSAGE_DB_KEY, &rnd);
if m_type == MessageType::Multisig {
@ -52,9 +54,9 @@ pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Messa
}
info!("creating message: {}", &f_mid);
let created = chrono::offset::Utc::now().timestamp();
// get contact public gpg key and encipher the message
// get contact public message key and encipher the message
debug!("sending message: {:?}", &m);
let contact: Contact = contact::find(&m.to);
let contact: Contact = contact::find(&m.to).map_err(|_| NevekoError::Message)?;
let hex_nmpk: String = contact.nmpk;
let encipher = Some(String::from(neveko25519::ENCIPHER));
let e_body = neveko25519::cipher(&hex_nmpk, String::from(&m.body), encipher).await;
@ -67,35 +69,47 @@ pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Messa
to: String::from(&m.to),
};
debug!("insert message: {:?}", &new_message);
let s = db::DatabaseEnvironment::open();
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_message.mid;
db::DatabaseEnvironment::write(&s.env, &s.handle, k, &Message::to_db(&new_message));
let message = bincode::serialize(&new_message).unwrap_or_default();
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all message, write keys to with ml
let list_key = crate::MESSAGE_LIST_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key));
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating message index");
}
let msg_list = [r, String::from(&f_mid)].join(",");
let d_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [d_r, String::from(&f_mid)].join(",");
debug!("writing message index {} for id: {}", msg_list, list_key);
db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
info!("attempting to send message");
let send = send_message(&new_message, &jwp, m_type).await;
send.unwrap();
new_message
Ok(new_message)
}
/// Rx message
pub async fn rx(m: Json<Message>) {
pub async fn rx(m: Json<Message>) -> Result<(), NevekoError>{
info!("rx from: {}", &m.from);
// make sure the message isn't something strange
let is_valid = validate_message(&m);
if !is_valid {
return;
error!("invalid contact");
return Err(NevekoError::Contact);
}
// don't allow messages from outside the contact list
let is_in_contact_list = contact::exists(&m.from);
let is_in_contact_list = contact::exists(&m.from)
.map_err(|_| NevekoError::Contact)?;
if !is_in_contact_list {
return;
error!("not a mutual contact");
return Err(NevekoError::Contact);
}
let f_mid: String = format!("{}{}", crate::MESSAGE_DB_KEY, utils::generate_rnd());
let new_message = Message {
@ -107,30 +121,41 @@ pub async fn rx(m: Json<Message>) {
to: String::from(&m.to),
};
debug!("insert message: {:?}", &new_message);
let s = db::DatabaseEnvironment::open();
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_message.mid;
db::DatabaseEnvironment::write(&s.env, &s.handle, k, &Message::to_db(&new_message));
let message = bincode::serialize(&new_message).unwrap_or_default();
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all message, write keys to with rx
let list_key = crate::RX_MESSAGE_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key));
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating message index");
}
let msg_list = [r, String::from(&f_mid)].join(",");
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [old, String::from(&f_mid)].join(",");
debug!("writing message index {} for {}", msg_list, list_key);
db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Parse the multisig message type and info
async fn parse_multisig_message(mid: String) -> MultisigMessageData {
let d: reqres::DecipheredMessageBody = decipher_body(mid).await;
async fn parse_multisig_message(mid: String) -> Result<MultisigMessageData, NevekoError> {
let d: reqres::DecipheredMessageBody = decipher_body(mid).await?;
let mut bytes = hex::decode(d.body.into_bytes()).unwrap_or_default();
let decoded = String::from_utf8(bytes).unwrap_or(String::new());
let values = decoded.split(":");
let mut v: Vec<String> = values.map(String::from).collect();
if v.len() != VALID_MSIG_MSG_LENGTH {
error!("invalid msig message length");
return Default::default();
return Err(NevekoError::Message);
}
let sub_type: String = v.remove(0);
let orid: String = v.remove(0);
@ -144,11 +169,13 @@ async fn parse_multisig_message(mid: String) -> MultisigMessageData {
}
bytes = Vec::new();
debug!("zero decipher bytes: {:?}", bytes);
MultisigMessageData {
info,
sub_type,
orid,
}
Ok(
MultisigMessageData {
info,
sub_type,
orid,
}
)
}
/// Rx multisig message
@ -171,16 +198,20 @@ async fn parse_multisig_message(mid: String) -> MultisigMessageData {
/// let key = "prepare-o123-test.b32.i2p";
/// let info_str = db::DatabaseEnvironment::read(&s.env, &s.handle, &key);
/// ```
pub async fn rx_multisig(m: Json<Message>) {
pub async fn rx_multisig(m: Json<Message>) -> Result<(), NevekoError> {
info!("rx multisig from: {}", &m.from);
// make sure the message isn't something strange
let is_valid = validate_message(&m);
if !is_valid {
return;
error!("invalid contact");
return Err(NevekoError::Contact);
}
// don't allow messages from outside the contact list
let is_in_contact_list = contact::exists(&m.from);
let is_in_contact_list = contact::exists(&m.from)
.map_err(|_| NevekoError::Contact)?;
if !is_in_contact_list {
return;
error!("not a mutual contact");
return Err(NevekoError::Contact);
}
let f_mid: String = format!("msig{}", utils::generate_rnd());
let new_message = Message {
@ -191,76 +222,99 @@ pub async fn rx_multisig(m: Json<Message>) {
created: chrono::offset::Utc::now().timestamp(),
to: String::from(&m.to),
};
let s = db::DatabaseEnvironment::async_open().await;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_message.mid;
db::DatabaseEnvironment::async_write(&s.env, &s.handle, k, &Message::to_db(&new_message)).await;
let message = bincode::serialize(&new_message).unwrap_or_default();
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, k.as_bytes(), &message)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all msig messages, write keys to with msigl
let list_key = crate::MSIG_MESSAGE_LIST_DB_KEY;
let r = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &String::from(list_key)).await;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating msig message index");
}
let msg_list = [r, String::from(&f_mid)].join(",");
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let msg_list = [old, String::from(&f_mid)].join(",");
debug!(
"writing msig message index {} for id: {}",
msg_list, list_key
);
db::DatabaseEnvironment::async_write(&s.env, &s.handle, &String::from(list_key), &msg_list).await;
let data: MultisigMessageData = parse_multisig_message(new_message.mid).await;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let data: MultisigMessageData = parse_multisig_message(new_message.mid).await?;
debug!(
"writing multisig message type {} for order {}",
&data.sub_type, &data.orid
);
// lookup msig message data by {type}-{order id}-{contact .b32.i2p address}
// store info as {a_info}:{a_info (optional)}
let s_msig = db::DatabaseEnvironment::async_open().await;
let s_msig = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let msig_key = format!("{}-{}-{}", &data.sub_type, &data.orid, &m.from);
db::DatabaseEnvironment::async_write(&s_msig.env, &s_msig.handle, &msig_key, &data.info).await;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s_msig.env, handle, msig_key.as_bytes(), data.info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Message lookup
pub fn find(mid: &String) -> Message {
let s = db::DatabaseEnvironment::open();
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(mid));
/// Message lookup()
pub fn find(mid: &String) -> Result<Message, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &mid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("message not found");
return Default::default();
return Err(NevekoError::Message);
}
Message::from_db(String::from(mid), r)
let result: Message = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Message lookup
pub fn find_all() -> Vec<Message> {
let i_s = db::DatabaseEnvironment::open();
pub fn find_all() -> Result<Vec<Message>, NevekoError> {
let i_s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::MESSAGE_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("message index not found");
}
let i_r: String = bincode::deserialize(&i_r[..]).unwrap_or_default();
let i_v_mid = i_r.split(",");
let i_v: Vec<String> = i_v_mid.map(String::from).collect();
let mut messages: Vec<Message> = Vec::new();
for m in i_v {
let message: Message = find(&m);
let message: Message = find(&m)?;
if !message.mid.is_empty() {
messages.push(message);
}
}
let o_list_key = crate::RX_MESSAGE_DB_KEY;
let o_s = db::DatabaseEnvironment::open();
let o_r = db::DatabaseEnvironment::read(&o_s.env, &o_s.handle, &String::from(o_list_key));
let o_s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &o_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let o_r = db::DatabaseEnvironment::read(&o_s.env, handle, &o_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if o_r.is_empty() {
error!("message index not found");
}
let o_r: String = bincode::deserialize(&o_r[..]).unwrap_or_default();
let o_v_mid = o_r.split(",");
let o_v: Vec<String> = o_v_mid.map(String::from).collect();
for m in o_v {
let message: Message = find(&m);
let message: Message = find(&m)?;
if !message.mid.is_empty() {
messages.push(message);
}
}
messages
Ok(messages)
}
/// Tx message
@ -288,7 +342,7 @@ async fn send_message(out: &Message, jwp: &str, m_type: MessageType) -> Result<(
let status = response.status();
debug!("send response: {:?}", status.as_str());
if status == StatusCode::OK || status == StatusCode::PAYMENT_REQUIRED {
remove_from_fts(String::from(&out.mid));
remove_from_fts(String::from(&out.mid))?;
Ok(())
} else {
Ok(())
@ -300,25 +354,28 @@ async fn send_message(out: &Message, jwp: &str, m_type: MessageType) -> Result<(
}
}
} else {
send_to_retry(String::from(&out.mid)).await;
send_to_retry(String::from(&out.mid)).await?;
Ok(())
}
}
/// Returns deciphered message
pub async fn decipher_body(mid: String) -> reqres::DecipheredMessageBody {
let m = find(&mid);
let contact = contact::find_by_i2p_address(&m.from);
pub async fn decipher_body(mid: String) -> Result<reqres::DecipheredMessageBody, NevekoError> {
let m = find(&mid)?;
let contact = contact::find_by_i2p_address(&m.from)?;
let nmpk = contact.nmpk;
let message = String::from(&m.body);
let body = neveko25519::cipher(&nmpk, message, None).await;
reqres::DecipheredMessageBody { mid, body }
Ok(reqres::DecipheredMessageBody { mid, body })
}
/// Message deletion
pub fn delete(mid: &String) {
let s = db::DatabaseEnvironment::open();
db::DatabaseEnvironment::delete(&s.env, &s.handle, &String::from(mid));
pub fn delete(mid: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, handle, mid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// ping the contact health check over i2p
@ -354,48 +411,60 @@ async fn is_contact_online(contact: &String, jwp: String) -> Result<bool, Box<dy
}
/// stage message for async retry
async fn send_to_retry(mid: String) {
async fn send_to_retry(mid: String) -> Result<(), NevekoError>{
info!("sending {} to fts", &mid);
let s = db::DatabaseEnvironment::open();
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve FTS (failed-to-send), write keys to db with fts
let list_key = crate::FTS_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key));
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating fts message index");
}
let mut msg_list = [String::from(&r), String::from(&mid)].join(",");
let i_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let mut msg_list = [String::from(&i_r), String::from(&mid)].join(",");
// don't duplicate message ids in fts
if String::from(&r).contains(&String::from(&mid)) {
msg_list = r;
if String::from(&i_r).contains(&String::from(&mid)) {
msg_list = i_r;
}
debug!(
"writing fts message index {} for id: {}",
msg_list, list_key
);
db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// restart fts if not empty
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key));
let v_mid = r.split(",");
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let str_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let v_mid = str_r.split(",");
let v: Vec<String> = v_mid.map(String::from).collect();
debug!("fts contents: {:#?}", v);
let cleared = is_fts_clear(r);
let cleared = is_fts_clear(str_r);
if !cleared {
debug!("restarting fts");
utils::restart_retry_fts();
}
Ok(())
}
/// clear fts message from index
fn remove_from_fts(mid: String) {
fn remove_from_fts(mid: String) -> Result<(), NevekoError> {
info!("removing id {} from fts", &mid);
let s = db::DatabaseEnvironment::open();
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve FTS (failed-to-send), write keys to with fts
let list_key = crate::FTS_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key));
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("fts is empty");
}
let pre_v_fts = r.split(",");
let s_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let pre_v_fts = s_r.split(",");
let v: Vec<String> = pre_v_fts
.map(|s| {
if s != &mid {
@ -410,7 +479,11 @@ fn remove_from_fts(mid: String) {
"writing fts message index {} for id: {}",
msg_list, list_key
);
db::DatabaseEnvironment::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), msg_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Triggered on app startup, retries to send fts every minute
@ -418,42 +491,51 @@ fn remove_from_fts(mid: String) {
/// FTS thread terminates when empty and gets restarted on the next
///
/// failed-to-send message.
pub async fn retry_fts() {
pub async fn retry_fts() -> Result<(), NevekoError> {
let tick: std::sync::mpsc::Receiver<()> = schedule_recv::periodic_ms(crate::FTS_RETRY_INTERVAL);
loop {
debug!("running retry failed-to-send thread");
tick.recv().unwrap();
let s = db::DatabaseEnvironment::open();
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let list_key = crate::FTS_DB_KEY;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, &String::from(list_key));
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
info!("fts message index not found");
break; // terminate fts if no message to send
break Err(NevekoError::Database(MdbError::NotFound)); // terminate fts if no message to send
}
let v_mid = r.split(",");
let s_r: String = bincode::deserialize(&r[..]).unwrap_or_default();
let v_mid = s_r.split(",");
let v: Vec<String> = v_mid.map(String::from).collect();
debug!("fts contents: {:#?}", v);
let cleared = is_fts_clear(r);
let cleared = is_fts_clear(s_r);
if cleared {
// index was created but cleared
info!("terminating retry fts thread");
db::DatabaseEnvironment::delete(&s.env, &s.handle, list_key);
break;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
break Err(NevekoError::Database(MdbError::NotFound));
}
for m in v {
let message: Message = find(&m);
let message: Message = find(&m)?;
if !message.mid.is_empty() {
let s = db::DatabaseEnvironment::open();
// get jwp from db
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &message.to);
let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if !jwp.is_empty() {
let m_type = if message.mid.contains("msig") {
MessageType::Multisig
} else {
MessageType::Normal
};
send_message(&message, &jwp, m_type).await.unwrap();
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
send_message(&message, &str_jwp, m_type).await.unwrap();
} else {
error!("not jwp found for fts id: {}", &message.mid);
}
@ -488,14 +570,16 @@ fn is_fts_clear(r: String) -> bool {
/// Enciphers and sends the output from the monero-rpc
///
/// `prepare_multisig_info` method.
pub async fn send_prepare_info(orid: &String, contact: &String) {
let s = db::DatabaseEnvironment::open();
pub async fn send_prepare_info(orid: &String, contact: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let wallet_name = String::from(orid);
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let prepare_info = monero::prepare_wallet().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!(
"{}:{}:{}",
PREPARE_MSIG, orid, &prepare_info.result.multisig_info
@ -508,20 +592,24 @@ pub async fn send_prepare_info(orid: &String, contact: &String) {
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// Enciphers and sends the output from the monero-rpc
///
/// `make_multisig_info` method.
pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>) {
let s = db::DatabaseEnvironment::open();
pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let wallet_name = String::from(orid);
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let make_info = monero::make_wallet(info).await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!("{}:{}:{}", MAKE_MSIG, orid, &make_info.result.multisig_info);
let message: Message = Message {
body: body_str,
@ -531,7 +619,9 @@ pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>)
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// Enciphers and sends the output from the monero-rpc
@ -542,14 +632,16 @@ pub async fn send_exchange_info(
contact: &String,
info: Vec<String>,
kex_init: bool,
) {
let s = db::DatabaseEnvironment::open();
) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let wallet_name = String::from(orid);
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let exchange_info = monero::exchange_multisig_keys(false, info, &wallet_password).await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k);
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let mut body_str = format!(
"{}:{}:{}",
KEX_ONE_MSIG, orid, &exchange_info.result.multisig_info
@ -568,20 +660,24 @@ pub async fn send_exchange_info(
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// Enciphers and sends the output from the monero-rpc
///
/// `export_multisig_info` method.
pub async fn send_export_info(orid: &String, contact: &String) {
let s = db::DatabaseEnvironment::open();
pub async fn send_export_info(orid: &String, contact: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let wallet_name = String::from(orid);
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
let exchange_info = monero::export_multisig_info().await;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
let jwp = db::DatabaseEnvironment::read(&s.env, &s.handle, &k);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let body_str = format!("{}:{}:{}", EXPORT_MSIG, orid, &exchange_info.result.info);
let message: Message = Message {
body: body_str,
@ -591,7 +687,9 @@ pub async fn send_export_info(orid: &String, contact: &String) {
};
let j_message: Json<Message> = utils::message_to_json(&message);
monero::close_wallet(orid, &wallet_password).await;
create(j_message, jwp, MessageType::Multisig).await;
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
create(j_message, str_jwp, MessageType::Multisig).await?;
Ok(())
}
/// The customer or vendor (dispute only) needs to export
@ -599,7 +697,7 @@ pub async fn send_export_info(orid: &String, contact: &String) {
/// multisig info after funding. Once the info is imported
///
/// successfully the order needs to be updated to `MultisigComplete`.
pub async fn send_import_info(orid: &String, info: &Vec<String>) {
pub async fn send_import_info(orid: &String, info: &Vec<String>) -> Result<(), NevekoError> {
let wallet_name = String::from(orid);
let wallet_password = String::new();
monero::open_wallet(&wallet_name, &wallet_password).await;
@ -607,14 +705,15 @@ pub async fn send_import_info(orid: &String, info: &Vec<String>) {
monero::close_wallet(orid, &wallet_password).await;
if pre_import.result.n_outputs == 0 {
error!("unable to import multisig info for order: {}", orid);
return;
return Err(NevekoError::Database(MdbError::Panic))?;
}
let mut old_order = order::find(orid);
let mut old_order = order::find(orid)?;
let status = order::StatusType::MulitsigComplete.value();
old_order.status = String::from(&status);
let j_old_order = Json(old_order);
order::modify(j_old_order);
order::modify(j_old_order)?;
debug!("order: {} updated to: {}", orid, status);
Ok(())
}
/// Customer begins multisig orchestration by requesting the prepare info
@ -690,10 +789,12 @@ pub async fn d_trigger_msig_info(
mod tests {
use super::*;
async fn cleanup(k: &String) {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let s = db::DatabaseEnvironment::async_open().await;
db::DatabaseEnvironment::async_delete(&s.env, &s.handle, k).await;
fn cleanup(k: &String) -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle, k.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
#[test]
@ -721,24 +822,18 @@ mod tests {
#[test]
fn find_test() {
// run and async cleanup so the test doesn't fail when deleting test data
use tokio::runtime::Runtime;
let rt = Runtime::new().expect("Unable to create Runtime for test");
let _enter = rt.enter();
let body: String = String::from("test body");
let expected_message = Message {
body: body,
..Default::default()
};
let k = "test-key";
tokio::spawn(async move {
let s = db::DatabaseEnvironment::async_open().await;
db::DatabaseEnvironment::async_write(&s.env, &s.handle, k, &Message::to_db(&expected_message))
.await;
let actual_message: Message = find(&String::from(k));
assert_eq!(expected_message.body, actual_message.body);
cleanup(&String::from(k)).await;
});
Runtime::shutdown_background(rt);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let message = bincode::serialize(&new_message).unwrap_or_default();
db::write_chunks(&s.env, &s.handle, k, &message);
let actual_message: Message = find(&String::from(k));
assert_eq!(expected_message.body, actual_message.body);
cleanup(&String::from(k));
}
#[test]

View file

@ -5,7 +5,7 @@ use std::error::Error;
use crate::{
contact, db, error::NevekoError, i2p, models::*, monero, neveko25519, order, product, reqres, utils
};
use kn0sys_lmdb_rs::MdbError;
use kn0sys_lmdb_rs::MdbError::{self};
use log::{
debug,
error,
@ -34,7 +34,7 @@ impl StatusType {
}
/// Create a intial order
pub async fn create(j_order: Json<reqres::OrderRequest>) -> Result<Order, MdbError> {
pub async fn create(j_order: Json<reqres::OrderRequest>) -> Result<Order, NevekoError> {
info!("creating order");
let wallet_name = String::from(crate::APP_NAME);
let wallet_password =
@ -62,46 +62,62 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Result<Order, MdbErr
if !m_wallet {
error!("error creating msig wallet for order {}", &orid);
monero::close_wallet(&orid, &wallet_password).await;
return Err(MdbError::NotFound);
return Err(NevekoError::Order);
}
monero::close_wallet(&orid, &order_wallet_password).await;
debug!("insert order: {:?}", &new_order);
let s = db::DatabaseEnvironment::open()?;
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// inject adjudicator separately, modifying the order model is mendokusai
let adjudicator_k = format!("{}-{}", crate::ADJUDICATOR_DB_KEY, &orid);
db::write_chunks(&s.env, &s.handle?, adjudicator_k.as_bytes(), j_order.adjudicator.as_bytes());
db::write_chunks(&s.env, handle, adjudicator_k.as_bytes(), j_order.adjudicator.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_order.orid;
let s = db::DatabaseEnvironment::open()?;
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let order = bincode::serialize(&new_order).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &order);
db::write_chunks(&s.env, handle, k.as_bytes(), &order)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all orders, write keys to with ol
let list_key = crate::ORDER_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?;
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating order index");
}
let old: String = bincode::deserialize(&r[..]).unwrap_or_default();
let order_list = [old, String::from(&orid)].join(",");
debug!("writing order index {} for id: {}", order_list, list_key);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), &order_list.as_bytes());
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), &order_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(new_order)
}
/// Backup order for customer
pub fn backup(order: &Order) -> Result<(), MdbError> {
pub fn backup(order: &Order) -> Result<(), NevekoError> {
info!("creating backup of order: {}", order.orid);
let s = db::DatabaseEnvironment::open()?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &order.orid;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes());
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, handle, k.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let order_to_db = bincode::serialize(&order).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &order_to_db);
db::write_chunks(&s.env, handle, k.as_bytes(), &order_to_db)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all orders, write keys to with col
let list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating customer order index");
}
@ -112,29 +128,37 @@ pub fn backup(order: &Order) -> Result<(), MdbError> {
order_list = d_r;
}
debug!("writing order index {} for id: {}", order_list, list_key);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), order_list.as_bytes());
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), order_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Lookup order
pub fn find(oid: &String) -> Result<Order, MdbError> {
pub fn find(oid: &String) -> Result<Order, NevekoError> {
info!("find order: {}", &oid);
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &oid.as_bytes().to_vec())?;
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &oid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("order not found");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::NotFound));
}
let result: Order = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Lookup all orders from admin server
pub fn find_all() -> Result<Vec<Order>, MdbError> {
let i_s = db::DatabaseEnvironment::open()?;
pub fn find_all() -> Result<Vec<Order>, NevekoError> {
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle?, &i_list_key.as_bytes().to_vec())?;
let i_r = db::DatabaseEnvironment::read(&s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("order index not found");
}
@ -152,10 +176,13 @@ pub fn find_all() -> Result<Vec<Order>, MdbError> {
}
/// Lookup all orders that customer has saved from gui
pub fn find_all_backup() -> Result<Vec<Order>, MdbError> {
let i_s = db::DatabaseEnvironment::open()?;
pub fn find_all_backup() -> Result<Vec<Order>, NevekoError> {
let i_s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle?, &i_list_key.as_bytes().to_vec())?;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("customer order index not found");
}
@ -176,11 +203,14 @@ pub fn find_all_backup() -> Result<Vec<Order>, MdbError> {
}
/// Lookup all orders for customer
pub async fn find_all_customer_orders(cid: String) -> Result<Vec<Order>, MdbError> {
pub async fn find_all_customer_orders(cid: String) -> Result<Vec<Order>, NevekoError> {
info!("lookup orders for customer: {}", &cid);
let i_s = db::DatabaseEnvironment::open()?;
let i_s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle?, &i_list_key.as_bytes().to_vec())?;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("order index not found");
}
@ -198,11 +228,14 @@ pub async fn find_all_customer_orders(cid: String) -> Result<Vec<Order>, MdbErro
}
/// Lookup all orders for vendor
pub fn find_all_vendor_orders() -> Result<Vec<Order>, MdbError> {
pub fn find_all_vendor_orders() -> Result<Vec<Order>, NevekoError> {
info!("lookup orders for vendor");
let i_s = db::DatabaseEnvironment::open()?;
let i_s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::ORDER_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle?, &i_list_key.as_bytes().to_vec())?;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("order index not found");
}
@ -226,19 +259,25 @@ pub fn find_all_vendor_orders() -> Result<Vec<Order>, MdbError> {
}
/// Modify order from admin server
pub fn modify(o: Json<Order>) -> Result<Order, MdbError> {
pub fn modify(o: Json<Order>) -> Result<Order, NevekoError> {
info!("modify order: {}", &o.orid);
let f_order: Order = find(&o.orid)?;
if f_order.orid.is_empty() {
error!("order not found");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::NotFound));
}
let u_order = Order::update(String::from(&f_order.orid), &o);
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, &u_order.orid.as_bytes());
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, handle, &u_order.orid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let v = bincode::serialize(&u_order).unwrap_or_default();
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, &u_order.orid.as_bytes(), &v);
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::write_chunks(&s.env, handle, &u_order.orid.as_bytes(), &v)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(u_order)
}
@ -325,7 +364,7 @@ pub async fn cancel_order(orid: &String, signature: &String) -> Result<Order, Ne
}
// update the order status and send to customer
m_order.status = order::StatusType::Cancelled.value();
order::modify(Json(m_order));
order::modify(Json(m_order))?;
order::find(orid).map_err(|_| NevekoError::Order)
}
@ -356,7 +395,7 @@ pub async fn validate_order_for_ship(orid: &String) -> Result<reqres::FinalizeOr
&& r_balance.result.blocks_to_unlock < monero::LockTimeLimit::Blocks.value();
if ready_to_ship {
j_order.status = StatusType::Shipped.value();
order::modify(Json(j_order));
order::modify(Json(j_order))?;
}
let d_info: String = bincode::deserialize(&delivery_info[..]).unwrap_or_default();
let e_delivery_info: String = neveko25519::cipher(
@ -453,8 +492,9 @@ pub async fn upload_delivery_info(
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = String::from(crate::DELIVERY_INFO_DB_KEY);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, k.as_bytes(), delivery_info.as_bytes());
modify(Json(m_order));
db::write_chunks(&s.env, handle, k.as_bytes(), delivery_info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
modify(Json(m_order))?;
// trigger nasr, this will cause the customer's neveko instance to request the
// txset
let i2p_address = i2p::get_destination(None);
@ -520,7 +560,7 @@ pub async fn finalize_order(orid: &String) -> Result< reqres::FinalizeOrderRespo
}
monero::close_wallet(orid, &wallet_password).await;
m_order.status = order::StatusType::Delivered.value();
order::modify(Json(m_order));
order::modify(Json(m_order))?;
Ok(
reqres::FinalizeOrderResponse {
vendor_update_success: true,
@ -584,7 +624,7 @@ pub async fn trigger_finalize_request(
let unwrap: reqres::FinalizeOrderResponse = finalize.unwrap();
let mut m_order: Order = order::find(orid).map_err(|_| NevekoError::Order)?;
m_order.status = order::StatusType::Delivered.value();
backup(&m_order);
backup(&m_order)?;
Ok(unwrap)
}
@ -595,7 +635,7 @@ pub async fn d_trigger_finalize_request(
) -> Result<reqres::FinalizeOrderResponse, NevekoError> {
// ugh, sorry seems we need to get jwp for vendor from fts cache
// get jwp from db
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::NotFound))?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let jwp = db::DatabaseEnvironment::read(&s.env, handle, &k.as_bytes().to_vec())
@ -718,7 +758,11 @@ pub async fn transmit_sor_request(
/// A decomposition trigger for the shipping request so that the logic
///
/// can be executed from the gui.
pub async fn trigger_ship_request(contact: &String, jwp: &String, orid: &String) -> Order {
pub async fn trigger_ship_request(
contact: &String,
jwp: &String,
orid: &String
) -> Result<Order, NevekoError> {
info!("executing trigger_ship_request");
let data = String::from(orid);
let wallet_password =
@ -730,17 +774,21 @@ pub async fn trigger_ship_request(contact: &String, jwp: &String, orid: &String)
// cache order request to db
if order.is_err() {
log::error!("failed to trigger shipping request");
return Default::default();
return Err(NevekoError::Order);
}
let unwrap_order: Order = order.unwrap();
backup(&unwrap_order);
unwrap_order
backup(&unwrap_order)?;
Ok(unwrap_order)
}
/// A post-decomposition trigger for the cancel request so that the logic
///
/// can be executed from the gui.
pub async fn trigger_cancel_request(contact: &String, jwp: &String, orid: &String) -> Order {
pub async fn trigger_cancel_request(
contact: &String,
jwp: &String,
orid: &String
) -> Result<Order, NevekoError> {
info!("executing trigger_cancel_request");
let data = String::from(orid);
let wallet_password =
@ -752,11 +800,11 @@ pub async fn trigger_cancel_request(contact: &String, jwp: &String, orid: &Strin
// cache order request to db
if order.is_err() {
log::error!("failed to trigger cancel request");
return Default::default();
return Err(NevekoError::Order);
}
let unwrap_order: Order = order.unwrap();
backup(&unwrap_order);
unwrap_order
backup(&unwrap_order)?;
Ok(unwrap_order)
}
/// Decomposition trigger for the shipping request
@ -772,7 +820,7 @@ pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Result<O
info!("executing d_trigger_ship_request");
// request shipment if the order status is MultisigComplete
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let trigger = trigger_ship_request(contact, &str_jwp, orid).await;
let trigger = trigger_ship_request(contact, &str_jwp, orid).await?;
if trigger.status == order::StatusType::MulitsigComplete.value() {
let ship_res = transmit_ship_request(contact, &str_jwp, orid).await;
if ship_res.is_err() {
@ -785,7 +833,8 @@ pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Result<O
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, key.as_bytes(), hex_delivery_info.as_bytes());
db::write_chunks(&s.env, handle, key.as_bytes(), hex_delivery_info.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
Ok(trigger)
}
@ -846,7 +895,7 @@ pub async fn d_trigger_cancel_request(contact: &String, orid: &String) -> Result
let order: Order = order::find(orid).map_err(|_| NevekoError::Order)?;
if order.status != order::StatusType::MulitsigComplete.value() {
let str_jwp: String = bincode::deserialize(&jwp[..]).unwrap_or_default();
let trigger = trigger_cancel_request(contact, &str_jwp, orid).await;
let trigger = trigger_cancel_request(contact, &str_jwp, orid).await?;
if trigger.status == order::StatusType::Cancelled.value() {
return Ok(trigger);
}

View file

@ -1,9 +1,7 @@
//! Marketplace products upload, modification, etc module
use crate::{
db,
models::*,
utils,
db, error::NevekoError, models::*, utils
};
use kn0sys_lmdb_rs::MdbError;
use log::{
@ -15,11 +13,11 @@ use rocket::serde::json::Json;
use std::error::Error;
/// Create a new product
pub fn create(d: Json<Product>) -> Result<Product, MdbError> {
pub fn create(d: Json<Product>) -> Result<Product, NevekoError> {
let pid: String = format!("{}{}", crate::PRODUCT_DB_KEY, utils::generate_rnd());
if !validate_product(&d) {
error!("invalid product");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::NotFound));
}
let new_product = Product {
pid: String::from(&pid),
@ -31,14 +29,18 @@ pub fn create(d: Json<Product>) -> Result<Product, MdbError> {
qty: d.qty,
};
debug!("insert product: {:?}", &new_product);
let s = db::DatabaseEnvironment::open()?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let k = &new_product.pid;
let product = bincode::serialize(&new_product).unwrap_or_default();
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), &product);
db::write_chunks(&s.env, handle, k.as_bytes(), &product)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
// in order to retrieve all products, write keys to with pl
let list_key = crate::PRODUCT_LIST_DB_KEY;
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &list_key.as_bytes().to_vec())?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
debug!("creating product index");
}
@ -48,28 +50,34 @@ pub fn create(d: Json<Product>) -> Result<Product, MdbError> {
"writing product index {} for id: {}",
product_list, list_key
);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, list_key.as_bytes(), product_list.as_bytes());
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, list_key.as_bytes(), product_list.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(new_product)
}
/// Single Product lookup
pub fn find(pid: &String) -> Result<Product, MdbError> {
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &pid.as_bytes().to_vec())?;
pub fn find(pid: &String) -> Result<Product, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &pid.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("product not found");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::NotFound));
}
let result: Product = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Product lookup for all
pub fn find_all() -> Result<Vec<Product>, MdbError> {
let i_s = db::DatabaseEnvironment::open()?;
pub fn find_all() -> Result<Vec<Product>, NevekoError> {
let i_s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_list_key = crate::PRODUCT_LIST_DB_KEY;
let i_r = db::DatabaseEnvironment::read(&i_s.env, &i_s.handle?, &i_list_key.as_bytes().to_vec())?;
let handle = &i_s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let i_r = db::DatabaseEnvironment::read(&i_s.env, handle, &i_list_key.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if i_r.is_empty() {
error!("product index not found");
}
@ -89,20 +97,23 @@ pub fn find_all() -> Result<Vec<Product>, MdbError> {
}
/// Modify product
pub fn modify(p: Json<Product>) -> Result<Product, MdbError> {
pub fn modify(p: Json<Product>) -> Result<Product, NevekoError> {
// TODO(c2m): don't allow modification to products with un-delivered orders
info!("modify product: {}", &p.pid);
let f_prod: Product = find(&p.pid)?;
if f_prod.pid.is_empty() {
error!("product not found");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::NotFound));
}
let u_prod = Product::update(f_prod, &p);
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, u_prod.pid.as_bytes())?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let _ = db::DatabaseEnvironment::delete(&s.env, handle, u_prod.pid.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let product = bincode::serialize(&u_prod).unwrap_or_default();
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, u_prod.pid.as_bytes(), &product);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, u_prod.pid.as_bytes(), &product)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(u_prod)
}

View file

@ -1,11 +1,9 @@
//! External authorization module via JWPs
use crate::{
db,
monero,
reqres,
utils,
db, error::NevekoError, monero, reqres, utils
};
use kn0sys_lmdb_rs::MdbError;
use log::{
error,
info,
@ -125,9 +123,10 @@ pub async fn prove_payment(contact: String, txp: &TxProof) -> Result<reqres::Jwp
let s = db::DatabaseEnvironment::open()?;
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?;
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle?, k.as_bytes())?;
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, &k.as_bytes(), &r.jwp.as_bytes().to_vec());
db::write_chunks(&s.env, &s.handle?, &k.as_bytes(), &r.jwp.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(r)
}
_ => Ok(Default::default()),

View file

@ -812,7 +812,7 @@ pub struct XmrRpcQueryKeyResponse {
// END XMR Structs
/// Container for the message decipher
#[derive(Debug, Default, Deserialize)]
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct DecipheredMessageBody {
pub mid: String,

View file

@ -1,16 +1,7 @@
//! Generic functions for startup and convenience
use crate::{
args,
contact,
db,
dispute,
i2p,
message,
models,
monero,
neveko25519,
reqres,
args, contact, db, dispute, error::NevekoError, i2p, message, models, monero, neveko25519, reqres
};
use clap::Parser;
use kn0sys_lmdb_rs::MdbError;
@ -60,21 +51,6 @@ impl Default for ContactStatus {
}
}
/// Enum for selecting hash validation
#[derive(PartialEq)]
enum ExternalSoftware {
I2PZero,
XMR,
}
/// Handles the state for the installation manager popup
#[derive(Default)]
pub struct Installations {
pub xmr: bool,
pub i2p_zero: bool,
}
/// Handles the state for the connection manager popup
pub struct Connections {
pub blockchain_dir: String,
@ -406,7 +382,7 @@ async fn gen_app_wallet(password: &String) {
}
/// Secret keys for signing internal/external auth tokens
fn gen_signing_keys() -> Result<(), MdbError> {
fn gen_signing_keys() -> Result<(), NevekoError> {
info!("generating signing keys");
let jwp = get_jwp_secret_key()?;
let jwt = get_jwt_secret_key()?;
@ -414,14 +390,18 @@ fn gen_signing_keys() -> Result<(), MdbError> {
if jwp.is_empty() {
let mut data = [0u8; 32];
rand::thread_rng().fill_bytes(&mut data);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, crate::NEVEKO_JWP_SECRET_KEY.as_bytes(), &data);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, crate::NEVEKO_JWP_SECRET_KEY.as_bytes(), &data)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
if jwt.is_empty() {
let mut data = [0u8; 32];
rand::thread_rng().fill_bytes(&mut data);
let s = db::DatabaseEnvironment::open()?;
db::write_chunks(&s.env, &s.handle?, crate::NEVEKO_JWT_SECRET_KEY.as_bytes(), &data);
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::write_chunks(&s.env, handle, crate::NEVEKO_JWT_SECRET_KEY.as_bytes(), &data)
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
Ok(())
}
@ -429,75 +409,84 @@ fn gen_signing_keys() -> Result<(), MdbError> {
/// TODO(c2m): add a button to gui to call this
///
/// dont' forget to generate new keys as well
pub fn revoke_signing_keys() -> Result<(), MdbError> {
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, crate::NEVEKO_JWT_SECRET_KEY.as_bytes());
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, crate::NEVEKO_JWP_SECRET_KEY.as_bytes());
pub fn revoke_signing_keys() -> Result<(), NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::DatabaseEnvironment::delete(&s.env, handle, crate::NEVEKO_JWT_SECRET_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::DatabaseEnvironment::delete(&s.env, handle, crate::NEVEKO_JWP_SECRET_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
pub fn get_jwt_secret_key() -> Result<String, MdbError> {
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &crate::NEVEKO_JWT_SECRET_KEY.as_bytes().to_vec())?;
pub fn get_jwt_secret_key() -> Result<String, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &crate::NEVEKO_JWT_SECRET_KEY.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("JWT key not found");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::Panic));
}
let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
pub fn get_jwp_secret_key() -> Result<String, MdbError> {
pub fn get_jwp_secret_key() -> Result<String, NevekoError> {
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &crate::NEVEKO_JWP_SECRET_KEY.as_bytes().to_vec())?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &crate::NEVEKO_JWP_SECRET_KEY.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("JWP key not found");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::NotFound));
}
let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
/// Returns the hex encoded neveko message public key from LMDB
pub fn get_nmpk() -> Result<String, MdbError> {
let s = db::DatabaseEnvironment::open()?;
let r = db::DatabaseEnvironment::read(&s.env, &s.handle?, &crate::NEVEKO_NMPK.as_bytes().to_vec())?;
pub fn get_nmpk() -> Result<String, NevekoError> {
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let r = db::DatabaseEnvironment::read(&s.env, handle, &crate::NEVEKO_NMPK.as_bytes().to_vec())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if r.is_empty() {
error!("neveko message public key not found");
return Err(MdbError::NotFound);
return Err(NevekoError::Database(MdbError::Panic));
}
let result: String = bincode::deserialize(&r[..]).unwrap_or_default();
Ok(result)
}
async fn generate_nmpk() -> Result<(), MdbError> {
async fn generate_nmpk() -> Result<(), NevekoError> {
info!("generating neveko message public key");
let nmpk: String = get_nmpk()?;
// send to db
let s = db::DatabaseEnvironment::open()?;
let s = db::DatabaseEnvironment::open().map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
if nmpk.is_empty() {
let nmk: neveko25519::NevekoMessageKeys = neveko25519::generate_neveko_message_keys().await;
db::write_chunks(&s.env, &s.handle?, crate::NEVEKO_NMPK.as_bytes(), nmk.hex_nmpk.as_bytes());
db::write_chunks(&s.env, handle, crate::NEVEKO_NMPK.as_bytes(), nmk.hex_nmpk.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
}
Ok(())
}
/// Put all app pre-checks here
pub async fn start_up() {
pub async fn start_up() -> Result<(), NevekoError> {
info!("neveko is starting up");
warn!("monero multisig is experimental and usage of neveko may lead to loss of funds");
let args = args::Args::parse();
if args.clear_fts {
clear_fts();
clear_fts()?;
}
if args.clear_disputes {
clear_disputes();
clear_disputes()?;
}
gen_signing_keys();
gen_signing_keys()?;
if !is_using_remote_node() {
monero::start_daemon();
}
@ -518,7 +507,7 @@ pub async fn start_up() {
wallet_password = read_password().unwrap();
std::env::set_var(crate::MONERO_WALLET_PASSWORD, &wallet_password);
}
generate_nmpk().await;
generate_nmpk().await?;
let env: String = get_release_env().value();
if !args.i2p_advanced {
i2p::start().await;
@ -527,11 +516,12 @@ pub async fn start_up() {
// start async background tasks here
{
tokio::spawn(async {
message::retry_fts().await;
dispute::settle_dispute().await;
let _ = message::retry_fts().await;
let _ = dispute::settle_dispute().await;
});
}
info!("{} - neveko is online", env);
Ok(())
}
/// TODO(?): get rid of this after implementing monero bindings
@ -567,30 +557,36 @@ pub fn kill_child_processes(cm: bool) {
/// We can restart fts from since it gets terminated when empty
pub fn restart_retry_fts() {
tokio::spawn(async move {
message::retry_fts().await;
let _ = message::retry_fts().await;
});
}
/// We can restart dispute auto-settle from since it gets terminated when empty
pub fn restart_dispute_auto_settle() {
tokio::spawn(async move {
dispute::settle_dispute().await;
let _ = dispute::settle_dispute().await;
});
}
/// Called on app startup if `--clear-fts` flag is passed.
fn clear_fts() -> Result<(), MdbError> {
fn clear_fts() -> Result<(), NevekoError> {
info!("clear fts");
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, crate::FTS_DB_KEY.as_bytes());
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::DatabaseEnvironment::delete(&s.env, handle, crate::FTS_DB_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
/// Called on app startup if `--clear-dispute` flag is passed.
fn clear_disputes() -> Result<(), MdbError> {
fn clear_disputes() -> Result<(), NevekoError> {
info!("clear_disputes");
let s = db::DatabaseEnvironment::open()?;
db::DatabaseEnvironment::delete(&s.env, &s.handle?, crate::DISPUTE_LIST_DB_KEY.as_bytes());
let s = db::DatabaseEnvironment::open()
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
let handle = &s.handle.map_err(|_| NevekoError::Database(MdbError::Panic))?;
db::DatabaseEnvironment::delete(&s.env, handle, crate::DISPUTE_LIST_DB_KEY.as_bytes())
.map_err(|_| NevekoError::Database(MdbError::Panic))?;
Ok(())
}
@ -710,7 +706,7 @@ pub fn toggle_vendor_enabled() -> Result<bool, MdbError> {
&s.handle?,
contact::NEVEKO_VENDOR_ENABLED.as_bytes(),
contact::NEVEKO_VENDOR_MODE_ON.as_bytes(),
);
)?;
Ok(true)
} else {
info!("neveko vendor mode disabled");
@ -720,7 +716,7 @@ pub fn toggle_vendor_enabled() -> Result<bool, MdbError> {
&s.handle?,
contact::NEVEKO_VENDOR_ENABLED.as_bytes(),
contact::NEVEKO_VENDOR_MODE_OFF.as_bytes(),
);
)?;
Ok(false)
}
}
@ -736,7 +732,7 @@ pub fn search_gui_db(f: String, data: String) -> Result<String, MdbError> {
pub fn write_gui_db(f: String, key: String, data: String) -> Result<(), MdbError> {
let s = db::DatabaseEnvironment::open()?;
let k = format!("{}-{}", f, key);
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), data.as_bytes());
db::write_chunks(&s.env, &s.handle?, k.as_bytes(), data.as_bytes())?;
Ok(())
}

View file

@ -26,6 +26,7 @@ wgpu = ["eframe/wgpu", "bytemuck"]
[dependencies]
bincode = "1.3.3"
chrono = { version = "0.4", features = ["js-sys", "wasmbind"] }
eframe = { version = "0.21.0", path = "./crates/eframe", default-features = false }
egui = { version = "0.21.0", path = "./crates/egui", features = [

View file

@ -197,7 +197,7 @@ impl eframe::App for AddressBookApp {
// initial contact load
if !self.contacts_init {
self.contacts = contact::find_all();
self.contacts = contact::find_all().unwrap_or_default();
self.contacts_init = true;
}
@ -347,9 +347,9 @@ impl eframe::App for AddressBookApp {
&& self.status.jwp.is_empty();
if !self.status.jwp.is_empty() || failed_to_prove {
if ui.button("Clear stale JWP").clicked() {
utils::clear_gui_db(String::from("gui-txp"), self.status.i2p.clone());
utils::clear_gui_db(String::from("gui-jwp"), self.status.i2p.clone());
utils::clear_gui_db(String::from("gui-exp"), self.status.i2p.clone());
utils::clear_gui_db(String::from("gui-txp"), self.status.i2p.clone()).unwrap();
utils::clear_gui_db(String::from("gui-jwp"), self.status.i2p.clone()).unwrap();
utils::clear_gui_db(String::from("gui-exp"), self.status.i2p.clone()).unwrap();
self.showing_status = false;
}
}
@ -422,7 +422,7 @@ impl eframe::App for AddressBookApp {
self.contact = String::new();
self.is_adding = false;
self.approve_contact = false;
self.contacts = contact::find_all();
self.contacts = contact::find_all().unwrap_or_default();
for c in &self.contacts {
ui.label(format!("{}", c.i2p_address));
}
@ -541,10 +541,11 @@ impl eframe::App for AddressBookApp {
String::from(crate::GUI_NICK_DB_KEY),
String::from(&c.i2p_address),
);
let nick = if nick_db.is_empty() {
let u_nick = nick_db.unwrap_or_default();
let nick = if u_nick.is_empty() {
String::from("anon")
} else {
nick_db
u_nick
};
self.status.nick = nick;
self.status.i2p = String::from(&c.i2p_address);
@ -552,16 +553,16 @@ impl eframe::App for AddressBookApp {
self.status.txp = utils::search_gui_db(
String::from(crate::GUI_TX_PROOF_DB_KEY),
String::from(&c.i2p_address),
);
).unwrap_or_default();
// get the jwp
self.status.jwp = utils::search_gui_db(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&c.i2p_address),
);
).unwrap_or_default();
let r_exp = utils::search_gui_db(
String::from(crate::GUI_EXP_DB_KEY),
String::from(&c.i2p_address),
);
).unwrap_or_default();
self.status.exp = r_exp;
let expire = match self.status.exp.parse::<i64>() {
Ok(n) => n,
@ -622,8 +623,8 @@ fn send_create_contact_req(tx: Sender<models::Contact>, ctx: egui::Context, c: m
log::debug!("async send_create_contact_req");
tokio::spawn(async move {
let j_contact = utils::contact_to_json(&c);
let a_contact: models::Contact = contact::create(&j_contact).await;
let _ = tx.send(a_contact);
let a_contact = contact::create(&j_contact).await;
let _ = tx.send(a_contact.unwrap_or_default());
ctx.request_repaint();
});
}
@ -662,9 +663,9 @@ fn send_payment_req(
log::debug!("cleaning stale jwp values");
tokio::spawn(async move {
if !retry {
utils::clear_gui_db(String::from("gui-txp"), String::from(&contact));
utils::clear_gui_db(String::from("gui-jwp"), String::from(&contact));
utils::clear_gui_db(String::from("gui-exp"), String::from(&contact));
utils::clear_gui_db(String::from("gui-txp"), String::from(&contact)).unwrap();
utils::clear_gui_db(String::from("gui-jwp"), String::from(&contact)).unwrap();
utils::clear_gui_db(String::from("gui-exp"), String::from(&contact)).unwrap();
let ptxp_address = String::from(&d.address);
let ftxp_address = String::from(&d.address);
log::debug!("sending {} piconero(s) to: {}", &d.amount, &d.address);
@ -712,22 +713,22 @@ fn send_payment_req(
String::from(crate::GUI_TX_PROOF_DB_KEY),
String::from(&contact),
String::from(&ftxp.signature),
);
).unwrap();
utils::write_gui_db(
String::from(crate::GUI_TX_HASH_DB_KEY),
String::from(&contact),
String::from(&ftxp.hash),
);
).unwrap();
utils::write_gui_db(
String::from(crate::GUI_TX_SIGNATURE_DB_KEY),
String::from(&contact),
String::from(&ftxp.signature),
);
).unwrap();
utils::write_gui_db(
String::from(crate::GUI_TX_SUBADDRESS_DB_KEY),
String::from(&contact),
String::from(&ftxp.subaddress),
);
).unwrap();
log::debug!(
"proving payment to {} for: {}",
String::from(&contact),
@ -739,7 +740,7 @@ fn send_payment_req(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&contact),
String::from(&result.jwp),
);
).unwrap();
// this is just an estimate expiration but should suffice
let seconds: i64 = expire as i64 * 2 * 60;
let unix: i64 = chrono::offset::Utc::now().timestamp() + seconds;
@ -747,7 +748,7 @@ fn send_payment_req(
String::from(crate::GUI_EXP_DB_KEY),
String::from(&contact),
format!("{}", unix),
);
).unwrap();
ctx.request_repaint();
}
_ => log::error!("failed to obtain jwp"),
@ -758,9 +759,12 @@ fn send_payment_req(
let k_hash = String::from(crate::GUI_TX_HASH_DB_KEY);
let k_sig = String::from(crate::GUI_TX_SIGNATURE_DB_KEY);
let k_subaddress = String::from(crate::GUI_TX_SUBADDRESS_DB_KEY);
let hash = utils::search_gui_db(k_hash, String::from(&contact));
let signature = utils::search_gui_db(k_sig, String::from(&contact));
let subaddress = utils::search_gui_db(k_subaddress, String::from(&contact));
let hash = utils::search_gui_db(k_hash, String::from(&contact))
.unwrap_or_default();
let signature = utils::search_gui_db(k_sig, String::from(&contact))
.unwrap_or_default();
let subaddress = utils::search_gui_db(k_subaddress, String::from(&contact))
.unwrap_or_default();
let ftxp: proof::TxProof = proof::TxProof {
subaddress,
confirmations: 0,
@ -779,7 +783,7 @@ fn send_payment_req(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&contact),
String::from(&result.jwp),
);
).unwrap();
ctx.request_repaint();
}
_ => log::error!("failed to obtain jwp"),
@ -804,8 +808,9 @@ fn send_message_req(tx: Sender<bool>, ctx: egui::Context, body: String, to: Stri
tokio::spawn(async move {
let m_type = message::MessageType::Normal;
let result = message::create(j_message, jwp, m_type).await;
if !result.mid.is_empty() {
log::info!("sent message: {}", result.mid);
let u_res = result.unwrap_or_default();
if !u_res.mid.is_empty() {
log::info!("sent message: {}", u_res.mid);
let _ = tx.send(true);
ctx.request_repaint();
}
@ -814,12 +819,12 @@ fn send_message_req(tx: Sender<bool>, ctx: egui::Context, body: String, to: Stri
fn change_nick_req(contact: String, nick: String) {
log::debug!("change nick");
utils::clear_gui_db(String::from(crate::GUI_NICK_DB_KEY), String::from(&contact));
utils::clear_gui_db(String::from(crate::GUI_NICK_DB_KEY), String::from(&contact)).unwrap();
utils::write_gui_db(
String::from(crate::GUI_NICK_DB_KEY),
String::from(&contact),
nick,
);
).unwrap();
}
fn send_can_transfer_req(tx: Sender<bool>, ctx: egui::Context, invoice: u128) {

View file

@ -67,8 +67,6 @@ impl Default for HomeApp {
fn default() -> Self {
let blocks_fetched = 0;
let connections = Default::default();
let has_install_failed = false;
let installations = Default::default();
let is_core_running = false;
let is_editing_connections = false;
let is_init = true;
@ -87,7 +85,6 @@ impl Default for HomeApp {
let (wallet_height_tx, wallet_height_rx) = std::sync::mpsc::channel();
let (can_refresh_tx, can_refresh_rx) = std::sync::mpsc::channel();
let (i2p_status_tx, i2p_status_rx) = std::sync::mpsc::channel();
let (installation_tx, installation_rx) = std::sync::mpsc::channel();
let contents = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
let s_xmr_rpc_ver = Default::default();
let s_xmr_address = Default::default();
@ -175,13 +172,6 @@ impl eframe::App for HomeApp {
if let Ok(info) = self.xmrd_get_info_rx.try_recv() {
self.s_xmrd_get_info = info;
}
if let Ok(install) = self.installation_rx.try_recv() {
self.is_installing = !install;
if !install && self.is_loading {
self.has_install_failed = true
}
self.is_loading = false;
}
if let Ok(timeout) = self.core_timeout_rx.try_recv() {
self.is_timeout = true;
if timeout {
@ -424,7 +414,7 @@ impl eframe::App for HomeApp {
fn send_xmrd_get_info_req(tx: Sender<reqres::XmrDaemonGetInfoResponse>, ctx: egui::Context) {
tokio::spawn(async move {
let remote_var =
std::env::var(neveko_core::GUI_REMOTE_NODE).unwrap_or(utils::empty_string());
std::env::var(neveko_core::GUI_REMOTE_NODE).unwrap_or(String::new());
if remote_var == String::from(neveko_core::GUI_SET_REMOTE_NODE) {
let p_info = monero::p_get_info().await;
let info = p_info.unwrap_or(Default::default());

View file

@ -62,13 +62,18 @@ impl eframe::App for LockScreenApp {
self.lock_screen.credential.clone(),
);
// Get the credential hash from lmdb
let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap();
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, CREDENTIAL_KEY);
let s = db::DatabaseEnvironment::open().unwrap();
let r = db::DatabaseEnvironment::read(
&s.env,
&s.handle.unwrap(),
&CREDENTIAL_KEY.as_bytes().to_vec(),
).unwrap();
// hash the text entered and compare
let mut hasher = Sha512::new();
hasher.update(self.lock_screen.credential.clone());
let result = hasher.finalize();
let hex = hex::encode(&result[..]);
let r: String = bincode::deserialize(&r[..]).unwrap_or_default();
if hex == r {
self.is_locked = false;
}

View file

@ -51,7 +51,7 @@ impl eframe::App for MailBoxApp {
// initial message load
if !self.message_init {
self.messages = message::find_all();
self.messages = message::find_all().unwrap_or_default();
self.message_init = true;
}
@ -74,7 +74,7 @@ impl eframe::App for MailBoxApp {
egui::CentralPanel::default().show(ctx, |ui| {
if ui.button("Refresh").clicked() {
self.messages = message::find_all();
self.messages = message::find_all().unwrap_or_default();
}
ui.label("\n");
use egui_extras::{
@ -144,7 +144,7 @@ impl eframe::App for MailBoxApp {
}
}
if ui.button("Delete").clicked() {
message::delete(&m.mid);
message::delete(&m.mid).unwrap();
refresh_on_delete_req(
self.refresh_on_delete_tx.clone(),
ctx.clone(),
@ -173,7 +173,7 @@ fn decipher_req(m: &Message, tx: Sender<String>, ctx: egui::Context) {
let body: String = String::from(&m.body);
tokio::spawn(async move {
log::info!("async decipher_req");
let contact = contact::find_by_i2p_address(&from);
let contact = contact::find_by_i2p_address(&from).unwrap_or_default();
let deciphered = neveko25519::cipher(&contact.nmpk, body, None).await;
let _ = tx.send(deciphered);
ctx.request_repaint();

View file

@ -140,9 +140,14 @@ impl Default for MarketApp {
let (_refresh_on_delete_product_tx, _refresh_on_delete_product_rx) =
std::sync::mpsc::channel();
let read_product_image = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap();
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED);
let is_vendor_enabled = r == contact::NEVEKO_VENDOR_MODE_ON;
let s = db::DatabaseEnvironment::open().unwrap();
let r = db::DatabaseEnvironment::read(
&s.env,
&s.handle.unwrap(),
&contact::NEVEKO_VENDOR_ENABLED.as_bytes().to_vec(),
).unwrap();
let sr: String = bincode::deserialize(&r[..]).unwrap_or_default();
let is_vendor_enabled = sr == contact::NEVEKO_VENDOR_MODE_ON;
let (contact_info_tx, contact_info_rx) = std::sync::mpsc::channel();
let (get_vendor_products_tx, get_vendor_products_rx) = std::sync::mpsc::channel();
let (get_vendor_product_tx, get_vendor_product_rx) = std::sync::mpsc::channel();
@ -450,7 +455,8 @@ impl eframe::App for MarketApp {
let prefix = String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
if !self.msig.query_adjudicator {
let adjudicator_db =
utils::search_gui_db(String::from(&prefix), self.m_order.orid.clone());
utils::search_gui_db(String::from(&prefix), self.m_order.orid.clone())
.unwrap_or_default();
log::debug!("adjudicator db: {}", adjudicator_db);
self.msig.has_adjudicator = !adjudicator_db.is_empty();
self.msig.adjudicator = adjudicator_db;
@ -464,7 +470,7 @@ impl eframe::App for MarketApp {
prefix,
self.m_order.orid.clone(),
self.msig.adjudicator.clone(),
);
).unwrap();
self.msig.has_adjudicator = true;
}
} else {
@ -472,7 +478,7 @@ impl eframe::App for MarketApp {
ui.label("\t");
if !self.msig.completed_prepare {
if ui.button("Clear Mediator").clicked() {
utils::clear_gui_db(prefix, self.m_order.orid.clone());
utils::clear_gui_db(prefix, self.m_order.orid.clone()).unwrap();
self.msig.adjudicator = String::new();
self.msig.has_adjudicator = false;
self.msig.query_adjudicator = false;
@ -490,9 +496,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
// get prepare multisig info from vendor and adjudicator
// call prepare multisig and save to db
send_prepare_info_req(
@ -508,9 +516,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let sub_type = String::from(message::PREPARE_MSIG);
let is_prepared = validate_msig_step(
&adjudicator,
@ -531,9 +541,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
// get make multisig info from vendor and adjudicator
// call make multisig and save to db
send_make_info_req(
@ -549,9 +561,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let sub_type = String::from(message::MAKE_MSIG);
let is_made = validate_msig_step(
&adjudicator,
@ -572,9 +586,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
// get kex round one info from vendor and adjudicator
// call make multisig and save to db
send_kex_initial_req(
@ -590,9 +606,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let sub_type = String::from(message::KEX_ONE_MSIG);
let is_made = validate_msig_step(
&adjudicator,
@ -613,9 +631,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
// get kex round two info from vendor and adjudicator
// call make multisig and save to db
send_kex_final_req(
@ -631,9 +651,11 @@ impl eframe::App for MarketApp {
String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
let sub_type = String::from(message::KEX_TWO_MSIG);
let is_made = validate_msig_step(
&adjudicator,
@ -662,7 +684,8 @@ impl eframe::App for MarketApp {
self.is_loading = true;
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let contact =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
verify_order_wallet_funded(
&contact,
&self.m_order.orid,
@ -679,7 +702,8 @@ impl eframe::App for MarketApp {
self.is_loading = true;
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
// not much orchestration here afaik, just send the output to the vendor
// TODO(c2m): 'idk remember why this tx.clone() is being reused' but not
// nothing breaks for now...
@ -694,7 +718,7 @@ impl eframe::App for MarketApp {
let info = utils::search_gui_db(
String::from(crate::GUI_MSIG_EXPORT_DB_KEY),
String::from(&self.m_order.orid.clone()),
);
).unwrap_or_default();
if !info.is_empty() {
self.msig.completed_export = true;
}
@ -711,7 +735,8 @@ impl eframe::App for MarketApp {
)
.on_hover_text("Please wait for the vendor to upload delivery info.");
if ui.button("Check").clicked() {
let order = order::find(&self.m_order.orid.clone());
let order = order::find(&self.m_order.orid.clone())
.unwrap_or_default();
if order.status == order::StatusType::Shipped.value() {
self.msig.completed_shipping_request = true;
}
@ -753,7 +778,8 @@ impl eframe::App for MarketApp {
self.is_loading = true;
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
let vendor =
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone())
.unwrap_or_default();
// async trigger for signing and submitted the txset
release_txset(
vendor,
@ -898,7 +924,7 @@ impl eframe::App for MarketApp {
let e_info: String = utils::search_gui_db(
String::from(neveko_core::DELIVERY_INFO_DB_KEY),
String::from(&o.orid),
);
).unwrap_or_default();
cipher_req(
String::from(&o.cid),
e_info,
@ -917,7 +943,7 @@ impl eframe::App for MarketApp {
let vendor = utils::search_gui_db(
vendor_prefix,
self.m_order.orid.clone(),
);
).unwrap_or_default();
self.is_loading = true;
cancel_order_req(
self.cancel_request_tx.clone(),
@ -936,7 +962,7 @@ impl eframe::App for MarketApp {
let vendor = utils::search_gui_db(
vendor_prefix,
self.m_order.orid.clone(),
);
).unwrap_or_default();
self.is_loading = true;
create_dispute_req(
&self.m_order.orid.clone(),
@ -971,7 +997,8 @@ impl eframe::App for MarketApp {
}
let adjudicator_prefix = String::from(crate::GUI_MSIG_ADJUDICATOR_DB_KEY);
let adjudicator =
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone());
utils::search_gui_db(adjudicator_prefix, self.m_order.orid.clone())
.unwrap_or_default();
ui.label(format!("customer id: {}", self.new_order.cid));
ui.label(format!("adjudicator id: {}", adjudicator));
ui.label(format!("product id: {}", self.new_order.pid));
@ -1145,7 +1172,7 @@ impl eframe::App for MarketApp {
let nick_db = utils::search_gui_db(
String::from(crate::GUI_NICK_DB_KEY),
String::from(&v.i2p_address),
);
).unwrap_or_default();
let nick = if nick_db.is_empty() {
String::from("anon")
} else {
@ -1157,16 +1184,16 @@ impl eframe::App for MarketApp {
self.vendor_status.txp = utils::search_gui_db(
String::from(crate::GUI_TX_PROOF_DB_KEY),
String::from(&v.i2p_address),
);
).unwrap_or_default();
// get the jwp
self.vendor_status.jwp = utils::search_gui_db(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&v.i2p_address),
);
).unwrap_or_default();
let r_exp = utils::search_gui_db(
String::from(crate::GUI_EXP_DB_KEY),
String::from(&v.i2p_address),
);
).unwrap_or_default();
self.vendor_status.exp = r_exp;
let expire = match self.vendor_status.exp.parse::<i64>()
{
@ -1366,7 +1393,8 @@ impl eframe::App for MarketApp {
String::from(&p.pid),
);
} else {
let i_product = product::find(&p.pid);
let i_product = product::find(&p.pid)
.unwrap_or_default();
match std::fs::write(&file_path, &i_product.image) {
Ok(w) => w,
Err(_) => {
@ -1494,14 +1522,14 @@ impl eframe::App for MarketApp {
qty,
};
let j_product = utils::product_to_json(&product);
product::modify(j_product);
product::modify(j_product).unwrap();
self.new_product_desc = String::new();
self.new_product_name = String::new();
self.new_product_price = String::new();
self.new_product_qty = String::new();
self.new_product_image = String::new();
self.is_showing_product_update = false;
self.products = product::find_all();
self.products = product::find_all().unwrap_or_default();
}
if ui.button("Exit").clicked() {
self.new_product_desc = String::new();
@ -1619,8 +1647,8 @@ impl eframe::App for MarketApp {
.on_hover_text("monero multisig is experimental and usage of neveko may lead to loss of funds.");
});
if ui.button("Refresh").clicked() {
self.products = product::find_all();
self.orders = order::find_all();
self.products = product::find_all().unwrap_or_default();
self.orders = order::find_all().unwrap_or_default();
}
ui.horizontal(|ui| {
let vendor_mode: &str = if self.is_vendor_enabled {
@ -1630,17 +1658,17 @@ impl eframe::App for MarketApp {
};
ui.label(format!("vendor mode: {} \t", vendor_mode));
if ui.button("toggle").clicked() {
self.is_vendor_enabled = utils::toggle_vendor_enabled();
self.is_vendor_enabled = utils::toggle_vendor_enabled().unwrap_or_default();
}
});
if ui.button("View Vendors").clicked() {
// assume all contacts are vendors until updated status check
self.vendors = contact::find_all();
self.vendors = contact::find_all().unwrap_or_default();
self.is_showing_vendors = true;
}
ui.label("\n");
if ui.button("View Orders").clicked() {
self.customer_orders = order::find_all_backup();
self.customer_orders = order::find_all_backup().unwrap_or_default();
self.is_customer_viewing_orders = true;
}
if self.is_vendor_enabled {
@ -1697,7 +1725,7 @@ impl eframe::App for MarketApp {
qty,
};
let j_product = utils::product_to_json(&product);
product::create(j_product);
product::create(j_product).unwrap();
self.new_product_desc = String::new();
self.new_product_name = String::new();
self.new_product_price = String::new();
@ -1706,14 +1734,14 @@ impl eframe::App for MarketApp {
}
ui.label("\n");
if ui.button("View Products").clicked() {
self.products = product::find_all();
self.products = product::find_all().unwrap_or_default();
self.is_showing_products = true;
self.is_showing_vendors = false;
}
ui.label("\n");
if ui.button("Manage Orders").clicked() {
self.is_showing_orders = true;
self.orders = order::find_all_vendor_orders();
self.orders = order::find_all_vendor_orders().unwrap_or_default();
}
}
});
@ -1806,11 +1834,11 @@ fn submit_order_req(
let order = order::transmit_order_request(r_contact, jwp, request).await;
let u_order = order.unwrap_or_else(|_| Default::default());
// cache order request to db
order::backup(&u_order);
order::backup(&u_order).unwrap();
let prefix = String::from(crate::GUI_OVL_DB_KEY);
let orid = String::from(&u_order.orid);
let i2p = String::from(&contact);
utils::write_gui_db(prefix, orid, i2p);
utils::write_gui_db(prefix, orid, i2p).unwrap();
let _ = tx.send(u_order);
ctx.request_repaint();
});
@ -1830,9 +1858,10 @@ fn send_prepare_info_req(
let m_jwp: String = utils::search_gui_db(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&adjudicator),
);
).unwrap_or_default();
let v_jwp: String =
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor));
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor))
.unwrap_or_default();
let wallet_password = String::new();
monero::create_wallet(&w_orid, &wallet_password).await;
let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await;
@ -1850,10 +1879,10 @@ fn send_prepare_info_req(
String::from(crate::GUI_MSIG_PREPARE_DB_KEY),
String::from(&w_orid),
String::from(ref_prepare_info),
);
).unwrap();
// Request adjudicator and vendor while we're at it
// Will coordinating send this on make requests next
let s = db::DatabaseEnvironment::async_open().await;
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!(
"{}-{}-{}",
message::PREPARE_MSIG,
@ -1866,8 +1895,9 @@ fn send_prepare_info_req(
String::from(&v_orid),
vendor
);
let m_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await;
let v_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
let m_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let v_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
if v_prepare.is_empty() {
log::debug!(
"constructing vendor {} msig messages",
@ -1918,9 +1948,10 @@ fn send_make_info_req(
let m_jwp: String = utils::search_gui_db(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&adjudicator),
);
).unwrap_or_default();
let v_jwp: String =
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor));
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor))
.unwrap_or_default();
let wallet_password = String::new();
let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await;
if !m_wallet {
@ -1938,7 +1969,7 @@ fn send_make_info_req(
String::from(crate::GUI_MSIG_PREPARE_DB_KEY),
String::from(&w_orid),
);
let s = db::DatabaseEnvironment::async_open().await;
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!(
"{}-{}-{}",
message::PREPARE_MSIG,
@ -1951,18 +1982,22 @@ fn send_make_info_req(
String::from(&v_orid),
vendor
);
let m_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await;
let v_prepare = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
prepare_info_prep.push(String::from(&m_prepare));
prepare_info_prep.push(String::from(&v_prepare));
m_prepare_info_send.push(String::from(&c_prepare));
m_prepare_info_send.push(String::from(&v_prepare));
v_prepare_info_send.push(String::from(&m_prepare));
v_prepare_info_send.push(String::from(&c_prepare));
let m_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let sm_prepare: String = bincode::deserialize(&m_prepare[..]).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap();
let v_prepare = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
let sv_prepare: String = bincode::deserialize(&&v_prepare[..]).unwrap_or_default();
prepare_info_prep.push(String::from(&sm_prepare));
prepare_info_prep.push(String::from(&sv_prepare));
let uc_prepare = c_prepare.unwrap_or_default();
m_prepare_info_send.push(String::from(&uc_prepare));
m_prepare_info_send.push(String::from(&sv_prepare));
v_prepare_info_send.push(String::from(&sv_prepare));
v_prepare_info_send.push(String::from(&uc_prepare));
let local_make = utils::search_gui_db(
String::from(crate::GUI_MSIG_MAKE_DB_KEY),
String::from(&w_orid),
);
).unwrap_or_default();
if local_make.is_empty() {
let make_info = monero::make_wallet(prepare_info_prep).await;
monero::close_wallet(&w_orid, &wallet_password).await;
@ -1972,13 +2007,12 @@ fn send_make_info_req(
String::from(crate::GUI_MSIG_MAKE_DB_KEY),
String::from(&w_orid),
String::from(ref_make_info),
);
).unwrap();
}
}
// Request adjudicator and vendor while we're at it
// Will coordinating send this on make requests next
let s = db::DatabaseEnvironment::async_open().await;
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!(
"{}-{}-{}",
message::MAKE_MSIG,
@ -1991,8 +2025,9 @@ fn send_make_info_req(
String::from(&v_orid),
vendor
);
let m_make = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await;
let v_make = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
let m_make = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let v_make = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
if v_make.is_empty() {
log::debug!("constructing vendor {} msig messages", message::MAKE_MSIG);
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
@ -2040,9 +2075,10 @@ fn send_kex_initial_req(
let m_jwp: String = utils::search_gui_db(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&adjudicator),
);
).unwrap_or_default();
let v_jwp: String =
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor));
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor))
.unwrap_or_default();
let wallet_password = String::new();
let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await;
if !m_wallet {
@ -2059,8 +2095,8 @@ fn send_kex_initial_req(
let c_kex_init = utils::search_gui_db(
String::from(crate::GUI_MSIG_MAKE_DB_KEY),
String::from(&w_orid),
);
let s = db::DatabaseEnvironment::async_open().await;
).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!(
"{}-{}-{}",
message::MAKE_MSIG,
@ -2073,18 +2109,21 @@ fn send_kex_initial_req(
String::from(&v_orid),
vendor
);
let m_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await;
let v_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
kex_init_prep.push(String::from(&m_kex_init));
kex_init_prep.push(String::from(&v_kex_init));
let m_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let sm_kex_init: String = bincode::deserialize(&m_kex_init[..]).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap();
let v_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
let sv_kex_init: String = bincode::deserialize(&v_kex_init[..]).unwrap_or_default();
kex_init_prep.push(String::from(&sm_kex_init));
kex_init_prep.push(String::from(&sv_kex_init));
m_kex_init_send.push(String::from(&c_kex_init));
m_kex_init_send.push(String::from(&v_kex_init));
v_kex_init_send.push(String::from(&m_kex_init));
m_kex_init_send.push(String::from(&sv_kex_init));
v_kex_init_send.push(String::from(&sm_kex_init));
v_kex_init_send.push(String::from(&c_kex_init));
let local_kex_init = utils::search_gui_db(
String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY),
String::from(&w_orid),
);
).unwrap_or_default();
if local_kex_init.is_empty() {
let kex_out =
monero::exchange_multisig_keys(false, kex_init_prep, &wallet_password).await;
@ -2095,12 +2134,12 @@ fn send_kex_initial_req(
String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY),
String::from(&w_orid),
String::from(ref_kex_info),
);
).unwrap();
}
}
// Request adjudicator and vendor while we're at it
// Will coordinating send this on kex round two next
let s = db::DatabaseEnvironment::async_open().await;
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!(
"{}-{}-{}",
message::KEX_ONE_MSIG,
@ -2113,8 +2152,9 @@ fn send_kex_initial_req(
String::from(&v_orid),
vendor
);
let m_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await;
let v_kex_init = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
let m_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let v_kex_init = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
if v_kex_init.is_empty() {
log::debug!(
"constructing vendor {} msig messages",
@ -2165,9 +2205,10 @@ fn send_kex_final_req(
let m_jwp: String = utils::search_gui_db(
String::from(crate::GUI_JWP_DB_KEY),
String::from(&adjudicator),
);
).unwrap_or_default();
let v_jwp: String =
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor));
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor))
.unwrap_or_default();
let wallet_password = String::new();
let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await;
if !m_wallet {
@ -2182,8 +2223,8 @@ fn send_kex_final_req(
let c_kex_final = utils::search_gui_db(
String::from(crate::GUI_MSIG_KEX_ONE_DB_KEY),
String::from(&w_orid),
);
let s = db::DatabaseEnvironment::async_open().await;
).unwrap_or_default();
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!(
"{}-{}-{}",
message::KEX_ONE_MSIG,
@ -2196,8 +2237,11 @@ fn send_kex_final_req(
String::from(&v_orid),
vendor
);
let m_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await;
let v_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
let r_m_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let r_v_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
let m_kex_final: String = bincode::deserialize(&r_m_kex_final[..]).unwrap_or_default();
let v_kex_final: String = bincode::deserialize(&r_v_kex_final[..]).unwrap_or_default();
kex_final_prep.push(String::from(&m_kex_final));
kex_final_prep.push(String::from(&v_kex_final));
m_kex_final_send.push(String::from(&c_kex_final));
@ -2207,7 +2251,7 @@ fn send_kex_final_req(
let local_kex_final = utils::search_gui_db(
String::from(crate::GUI_MSIG_KEX_TWO_DB_KEY),
String::from(&w_orid),
);
).unwrap_or_default();
if local_kex_final.is_empty() {
let kex_out =
monero::exchange_multisig_keys(false, kex_final_prep, &wallet_password).await;
@ -2218,11 +2262,11 @@ fn send_kex_final_req(
String::from(crate::GUI_MSIG_KEX_TWO_DB_KEY),
String::from(&w_orid),
String::from(ref_kex_info),
);
).unwrap_or_default();
}
}
// we can verify all good if the senders all send back the correct wallet address
let s = db::DatabaseEnvironment::async_open().await;
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!(
"{}-{}-{}",
message::KEX_TWO_MSIG,
@ -2235,8 +2279,9 @@ fn send_kex_final_req(
String::from(&v_orid),
vendor
);
let m_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &m_msig_key).await;
let v_kex_final = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
let m_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let v_kex_final = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
if v_kex_final.is_empty() {
log::debug!(
"constructing vendor {} msig messages",
@ -2305,10 +2350,11 @@ fn verify_order_wallet_funded(
return;
}
monero::close_wallet(&order_id, &wallet_password).await;
let order = order::find(&order_id);
let order = order::find(&order_id).unwrap_or_default();
let vendor = String::from(&l_contact);
let v_jwp: String =
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor));
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor))
.unwrap_or_default();
let opid = String::from(&order.pid);
let result = product::get_vendor_product(vendor, v_jwp, opid).await;
if !result.is_ok() {
@ -2333,7 +2379,8 @@ fn send_import_info_req(tx: Sender<String>, ctx: egui::Context, orid: &String, v
let w_orid: String = String::from(orid);
tokio::spawn(async move {
let v_jwp: String =
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor));
utils::search_gui_db(String::from(crate::GUI_JWP_DB_KEY), String::from(&vendor))
.unwrap_or_default();
let wallet_password = String::new();
let m_wallet = monero::open_wallet(&w_orid, &wallet_password).await;
if !m_wallet {
@ -2350,17 +2397,17 @@ fn send_import_info_req(tx: Sender<String>, ctx: egui::Context, orid: &String, v
String::from(crate::GUI_MSIG_EXPORT_DB_KEY),
String::from(&w_orid),
String::from(ref_export_info),
);
).unwrap_or_default();
// Request vendor while we're at it
// Will coordinating send this on make requests next
let s = db::DatabaseEnvironment::async_open().await;
let s = db::DatabaseEnvironment::open().unwrap();
let v_msig_key = format!(
"{}-{}-{}",
message::EXPORT_MSIG,
String::from(&v_orid),
vendor
);
let v_export = db::DatabaseEnvironment::async_read(&s.env, &s.handle, &v_msig_key).await;
let v_export = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
if v_export.is_empty() {
log::debug!("constructing vendor {} msig messages", message::EXPORT_MSIG);
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
@ -2410,7 +2457,7 @@ fn cancel_order_req(
tokio::spawn(async move {
log::info!("cancel order req: {}", ship_orid);
let order = order::d_trigger_cancel_request(&vendor_i2p, &ship_orid).await;
let _ = tx.send(order);
let _ = tx.send(order.unwrap_or_default());
ctx.request_repaint();
});
}
@ -2422,11 +2469,14 @@ fn validate_msig_step(
vendor: &String,
sub_type: &String,
) -> bool {
let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let m_msig_key = format!("{}-{}-{}", sub_type, orid, adjudicator);
let v_msig_key = format!("{}-{}-{}", sub_type, orid, vendor);
let m_info = db::DatabaseEnvironment::read(&s.env, &s.handle, &m_msig_key);
let v_info = db::DatabaseEnvironment::read(&s.env, &s.handle, &v_msig_key);
let r_m_info = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &m_msig_key.as_bytes().to_vec()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let r_v_info = db::DatabaseEnvironment::read(&s.env, &s.handle.unwrap(), &v_msig_key.as_bytes().to_vec()).unwrap();
let m_info: String = bincode::deserialize(&&r_m_info[..]).unwrap_or_default();
let v_info: String = bincode::deserialize(&&r_v_info[..]).unwrap_or_default();
log::debug!("{} adjudicator info: {}", sub_type, &m_info);
log::debug!("{} vendor info: {}", sub_type, &v_info);
!m_info.is_empty() && !v_info.is_empty()
@ -2435,14 +2485,15 @@ fn validate_msig_step(
fn release_txset(contact: String, orid: String, ctx: egui::Context, tx: Sender<bool>) {
tokio::spawn(async move {
log::info!("async release txset");
let lookup = order::find(&orid);
let lookup = order::find(&orid).unwrap_or_default();
let submit = order::sign_and_submit_multisig(&orid, &lookup.vend_msig_txset).await;
if submit.result.tx_hash_list.is_empty() {
log::error!("could not submit txset");
let _ = tx.send(false);
return;
}
let finalize = order::d_trigger_finalize_request(&contact, &orid).await;
let t_finalize = order::d_trigger_finalize_request(&contact, &orid).await;
let finalize = t_finalize.unwrap_or_default();
// update order to delivered if success
let _ = tx.send(finalize.vendor_update_success);
ctx.request_repaint();
@ -2453,7 +2504,8 @@ fn release_txset(contact: String, orid: String, ctx: egui::Context, tx: Sender<b
fn upload_dinfo_req(dinfo: String, orid: String, ctx: egui::Context, tx: Sender<bool>) {
tokio::spawn(async move {
log::info!("async upload_dinfo_req");
let dinfo = order::upload_delivery_info(&orid, &dinfo).await;
let r_dinfo = order::upload_delivery_info(&orid, &dinfo).await;
let dinfo = r_dinfo.unwrap_or_default();
let _ = tx.send(!dinfo.orid.is_empty());
ctx.request_repaint();
});
@ -2492,7 +2544,8 @@ fn create_dispute_req(
tx_set: transfer.result.multisig_txset,
..Default::default()
};
let res = dispute::trigger_dispute_request(&a_contact, &dispute).await;
let t_res = dispute::trigger_dispute_request(&a_contact, &dispute).await;
let res = t_res.unwrap_or_default();
if res.created != 0 {
// cancel the order and write the dispute to the db
let wallet_password = std::env::var(neveko_core::MONERO_WALLET_PASSWORD)
@ -2500,9 +2553,9 @@ fn create_dispute_req(
monero::open_wallet(&String::from(neveko_core::APP_NAME), &wallet_password).await;
let pre_sign = monero::sign(String::from(&d_orid)).await;
monero::close_wallet(&String::from(neveko_core::APP_NAME), &wallet_password).await;
order::cancel_order(&d_orid, &pre_sign.result.signature).await;
let _ = order::cancel_order(&d_orid, &pre_sign.result.signature).await;
let j_dispute = utils::dispute_to_json(&res);
dispute::create(j_dispute);
let _ = dispute::create(j_dispute);
let _ = tx.send(res);
ctx.request_repaint();
}
@ -2512,7 +2565,7 @@ fn create_dispute_req(
fn cipher_req(cid: String, m: String, e: Option<String>, tx: Sender<String>, ctx: egui::Context) {
tokio::spawn(async move {
log::info!("async decipher_req");
let contact = contact::find(&cid);
let contact = contact::find(&cid).unwrap_or_default();
let ciphered = neveko25519::cipher(&contact.nmpk, m, e).await;
let _ = tx.send(ciphered);
ctx.request_repaint();

View file

@ -66,13 +66,14 @@ impl eframe::App for SettingsApp {
// TODO: don't open the database in the GUI
let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap();
let s = db::DatabaseEnvironment::open().unwrap();
let k = CREDENTIAL_KEY;
db::DatabaseEnvironment::delete(&s.env, &s.handle, &k);
let _ = db::DatabaseEnvironment::delete(&s.env, &s.handle.unwrap(), k.as_bytes()).unwrap();
let mut hasher = Sha512::new();
hasher.update(self.credential.clone());
let result = hasher.finalize();
db::write_chunks(&s.env, &s.handle, &k, &hex::encode(&result[..]));
let s = db::DatabaseEnvironment::open().unwrap();
db::write_chunks(&s.env, &s.handle.unwrap(), k.as_bytes(), hex::encode(&result[..]).as_bytes()).unwrap();
// update wallet rpc
change_wallet_password(
self.change_wallet_password_tx.clone(),

View file

@ -54,8 +54,8 @@ impl eframe::App for LoginApp {
let mut hasher = Sha512::new();
hasher.update(self.credential.clone());
let result = hasher.finalize();
let s = db::DatabaseEnvironment::open();
db::DatabaseEnvironment::write(&s.env, &s.handle, k, &hex::encode(&result[..]));
let s = db::DatabaseEnvironment::open().unwrap();
db::write_chunks(&s.env, &s.handle.unwrap(), k.as_bytes(), hex::encode(&result[..]).as_bytes()).unwrap();
self.credential = String::new();
}
});

View file

@ -236,8 +236,12 @@ impl WrapApp {
ctx.set_pixels_per_point(1.5);
// initial cred check, is there a better way to do this?
if !self.state.is_cred_set {
let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap();
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, crate::CREDENTIAL_KEY);
let s = db::DatabaseEnvironment::open().unwrap();
let r = db::DatabaseEnvironment::read(
&s.env,
&s.handle.unwrap(),
&crate::CREDENTIAL_KEY.as_bytes().to_vec(),
).unwrap();
if !r.is_empty() {
self.state.is_cred_set = true;
self.state.is_checking_cred = false;
@ -308,8 +312,12 @@ impl WrapApp {
loop {
log::debug!("check for cred");
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
let s = db::DatabaseEnvironment::open(&utils::get_release_env().value()).unwrap();
let r = db::DatabaseEnvironment::read(&s.env, &s.handle, crate::CREDENTIAL_KEY);
let s = db::DatabaseEnvironment::open().unwrap();
let r = db::DatabaseEnvironment::read(
&s.env,
&s.handle.unwrap(),
&crate::CREDENTIAL_KEY.as_bytes().to_vec()
).unwrap();
if r.is_empty() {
log::debug!("credential not found");
let _ = tx.send(false);

View file

@ -19,15 +19,15 @@ pub async fn create_product(
req_product: Json<models::Product>,
_token: auth::BearerToken,
) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::create(req_product);
Custom(Status::Created, Json(m_product))
let m_product = product::create(req_product);
Custom(Status::Created, Json(m_product.unwrap_or_default()))
}
/// Get a product by passing id
#[get("/<pid>")]
pub async fn get_product(pid: String, _token: auth::BearerToken) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::find(&pid);
Custom(Status::Ok, Json(m_product))
let m_product= product::find(&pid);
Custom(Status::Ok, Json(m_product.unwrap_or_default()))
}
/// Update product information
@ -36,29 +36,29 @@ pub async fn update_product(
product: Json<models::Product>,
_token: auth::BearerToken,
) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::modify(product);
Custom(Status::Ok, Json(m_product))
let m_product = product::modify(product);
Custom(Status::Ok, Json(m_product.unwrap_or_default()))
}
/// Return all products
#[get("/")]
pub async fn get_products(_token: auth::BearerToken) -> Custom<Json<Vec<models::Product>>> {
let m_products: Vec<models::Product> = product::find_all();
Custom(Status::Ok, Json(m_products))
let m_products = product::find_all();
Custom(Status::Ok, Json(m_products.unwrap_or_default()))
}
/// Get a order by passing id
#[get("/<orid>")]
pub async fn get_order(orid: String, _token: auth::BearerToken) -> Custom<Json<models::Order>> {
let m_order: models::Order = order::find(&orid);
Custom(Status::Ok, Json(m_order))
let m_order = order::find(&orid);
Custom(Status::Ok, Json(m_order.unwrap_or_default()))
}
/// Get all orders
#[get("/")]
pub async fn get_orders(_token: auth::BearerToken) -> Custom<Json<Vec<models::Order>>> {
let m_orders: Vec<models::Order> = order::find_all();
Custom(Status::Ok, Json(m_orders))
let m_orders = order::find_all();
Custom(Status::Ok, Json(m_orders.unwrap_or_default()))
}
/// Update order information
@ -67,8 +67,8 @@ pub async fn update_order(
order: Json<models::Order>,
_token: auth::BearerToken,
) -> Custom<Json<models::Order>> {
let m_order: models::Order = order::modify(order);
Custom(Status::Ok, Json(m_order))
let m_order = order::modify(order);
Custom(Status::Ok, Json(m_order.unwrap_or_default()))
}
/// Create a dispute
@ -77,15 +77,15 @@ pub async fn create_dispute(
dispute: Json<models::Dispute>,
_token: auth::BearerToken,
) -> Custom<Json<models::Dispute>> {
let m_dispute: models::Dispute = dispute::create(dispute);
Custom(Status::Ok, Json(m_dispute))
let m_dispute = dispute::create(dispute);
Custom(Status::Ok, Json(m_dispute.unwrap_or_default()))
}
/// Fetch a dispute
#[get("/<did>")]
pub async fn get_dispute(_token: auth::BearerToken, did: String) -> Custom<Json<models::Dispute>> {
let m_dispute: models::Dispute = dispute::find(&did);
Custom(Status::Ok, Json(m_dispute))
let m_dispute = dispute::find(&did);
Custom(Status::Ok, Json(m_dispute.unwrap_or_default()))
}
/// Sign and submit multisig
@ -113,12 +113,12 @@ pub async fn upload_delivery_info(
r_data: Json<reqres::FinalizeOrderResponse>,
_token: auth::BearerToken,
) -> Custom<Json<reqres::FinalizeOrderResponse>> {
let upload: reqres::FinalizeOrderResponse =
order::upload_delivery_info(&orid, &r_data.delivery_info).await;
if upload.delivery_info.is_empty() {
let upload = order::upload_delivery_info(&orid, &r_data.delivery_info).await;
let u_upload = upload.unwrap_or_default();
if u_upload.delivery_info.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Ok, Json(upload))
Custom(Status::Ok, Json(u_upload))
}
/// toggle vendor mode
@ -126,7 +126,7 @@ pub async fn upload_delivery_info(
pub async fn toggle_vendor_mode(
_token: auth::BearerToken,
) -> Custom<Json<reqres::VendorModeResponse>> {
let mode = utils::toggle_vendor_enabled();
let mode = utils::toggle_vendor_enabled().unwrap_or_default();
Custom(Status::Ok, Json(reqres::VendorModeResponse { mode }))
}
// END JSON APIs

View file

@ -29,23 +29,23 @@ pub async fn send_message(
} else {
message::MessageType::Normal
};
let res: Message = message::create(m_req, token.get_jwp(), m_type).await;
Custom(Status::Ok, Json(res))
let res = message::create(m_req, token.get_jwp(), m_type).await;
Custom(Status::Ok, Json(res.unwrap_or_default()))
}
/// Return all messages
#[get("/")]
pub async fn get_messages(_token: auth::BearerToken) -> Custom<Json<Vec<Message>>> {
let messages = message::find_all();
Custom(Status::Ok, Json(messages))
Custom(Status::Ok, Json(messages.unwrap_or_default()))
}
/// Delete a message by mid
#[delete("/<mid>")]
pub async fn remove_message(mid: String, _token: auth::BearerToken) -> Custom<Json<Vec<Message>>> {
message::delete(&mid);
let _ = message::delete(&mid);
let messages = message::find_all();
Custom(Status::Ok, Json(messages))
Custom(Status::Ok, Json(messages.unwrap_or_default()))
}
/// decipher a message body
@ -55,5 +55,5 @@ pub async fn decipher(
_token: auth::BearerToken,
) -> Custom<Json<reqres::DecipheredMessageBody>> {
let d_message = message::decipher_body(mid).await;
Custom(Status::Ok, Json(d_message))
}
Custom(Status::Ok, Json(d_message.unwrap_or_default()))
}

View file

@ -44,8 +44,8 @@ pub async fn get_i2p_status() -> Custom<Json<i2p::HttpProxyStatus>> {
/// Protected: false
#[get("/")]
pub async fn share_contact_info() -> Custom<Json<models::Contact>> {
let info: models::Contact = contact::share().await;
Custom(Status::Ok, Json(info))
let info = contact::share().await;
Custom(Status::Ok, Json(info.unwrap_or_default()))
}
/// Recieve messages here
@ -56,7 +56,7 @@ pub async fn rx_message(
_jwp: proof::PaymentProof,
message: Json<models::Message>,
) -> Custom<Json<models::Message>> {
message::rx(message).await;
let _ = message::rx(message).await;
Custom(Status::Ok, Json(Default::default()))
}
@ -84,8 +84,8 @@ pub async fn gen_jwp(proof: Json<proof::TxProof>) -> Custom<Json<reqres::Jwp>> {
/// Get a product by passing id
#[get("/<pid>")]
pub async fn get_product(pid: String, _jwp: proof::PaymentProof) -> Custom<Json<models::Product>> {
let m_product: models::Product = product::find(&pid);
Custom(Status::Ok, Json(m_product))
let m_product = product::find(&pid);
Custom(Status::Ok, Json(m_product.unwrap_or_default()))
}
/// Get all products
@ -93,7 +93,7 @@ pub async fn get_product(pid: String, _jwp: proof::PaymentProof) -> Custom<Json<
/// Protected: true
#[get("/products")]
pub async fn get_products(_jwp: proof::PaymentProof) -> Custom<Json<Vec<models::Product>>> {
let m_products: Vec<models::Product> = product::find_all();
let m_products: Vec<models::Product> = product::find_all().unwrap_or_default();
Custom(Status::Ok, Json(m_products))
}
@ -105,8 +105,8 @@ pub async fn create_order(
r_order: Json<reqres::OrderRequest>,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let m_order: models::Order = order::create(r_order).await;
Custom(Status::Created, Json(m_order))
let m_order = order::create(r_order).await;
Custom(Status::Created, Json(m_order.unwrap_or_default()))
}
/// Customer order retreival. Must send `signature`
@ -120,7 +120,8 @@ pub async fn retrieve_order(
signature: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let m_order = order::secure_retrieval(&orid, &signature).await;
let r_m_order = order::secure_retrieval(&orid, &signature).await;
let m_order = r_m_order.unwrap_or_default();
if m_order.cid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
@ -141,15 +142,15 @@ pub async fn get_multisig_info(
if r_info.init_adjudicator {
order::init_adjudicator_wallet(&r_info.orid).await;
}
message::send_prepare_info(&r_info.orid, &r_info.contact).await;
let _ = message::send_prepare_info(&r_info.orid, &r_info.contact).await;
} else if r_info.msig_type == *message::MAKE_MSIG {
message::send_make_info(&r_info.orid, &r_info.contact, info).await;
let _ = message::send_make_info(&r_info.orid, &r_info.contact, info).await;
} else if r_info.msig_type == *message::EXPORT_MSIG {
message::send_export_info(&r_info.orid, &r_info.contact).await;
let _ = message::send_export_info(&r_info.orid, &r_info.contact).await;
} else if r_info.msig_type == *message::IMPORT_MSIG {
message::send_import_info(&r_info.orid, &r_info.info).await;
let _ = message::send_import_info(&r_info.orid, &r_info.info).await;
} else {
message::send_exchange_info(&r_info.orid, &r_info.contact, info, r_info.kex_init).await;
let _ = message::send_exchange_info(&r_info.orid, &r_info.contact, info, r_info.kex_init).await;
}
Custom(Status::Ok, Json(Default::default()))
}
@ -162,7 +163,7 @@ pub async fn rx_multisig_message(
_jwp: proof::PaymentProof,
message: Json<models::Message>,
) -> Custom<Json<models::Message>> {
message::rx_multisig(message).await;
let _ = message::rx_multisig(message).await;
Custom(Status::Ok, Json(Default::default()))
}
@ -182,7 +183,8 @@ pub async fn request_shipment(
orid: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<reqres::FinalizeOrderResponse>> {
let finalize: reqres::FinalizeOrderResponse = order::validate_order_for_ship(&orid).await;
let r_finalize = order::validate_order_for_ship(&orid).await;
let finalize = r_finalize.unwrap_or_default();
if finalize.delivery_info.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
@ -204,7 +206,8 @@ pub async fn trigger_nasr(
vendor: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let order: models::Order = order::d_trigger_ship_request(&vendor, &orid).await;
let r_order = order::d_trigger_ship_request(&vendor, &orid).await;
let order = r_order.unwrap_or_default();
if order.orid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
@ -222,7 +225,8 @@ pub async fn cancel_order(
signature: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let m_order = order::cancel_order(&orid, &signature).await;
let r_m_order = order::cancel_order(&orid, &signature).await;
let m_order = r_m_order.unwrap_or_default();
if m_order.cid.is_empty() {
return Custom(Status::BadRequest, Json(Default::default()));
}
@ -239,7 +243,8 @@ pub async fn finalize_order(
orid: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<reqres::FinalizeOrderResponse>> {
let finalize = order::finalize_order(&orid).await;
let r_finalize = order::finalize_order(&orid).await;
let finalize = r_finalize.unwrap_or_default();
if !finalize.vendor_update_success {
return Custom(Status::BadRequest, Json(Default::default()));
}
@ -252,7 +257,8 @@ pub async fn create_dispute(
dispute: Json<models::Dispute>,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Dispute>> {
let m_dispute: models::Dispute = dispute::create(dispute);
let r_m_dispute = dispute::create(dispute);
let m_dispute = r_m_dispute.unwrap_or_default();
Custom(Status::Ok, Json(m_dispute))
}

View file

@ -19,7 +19,7 @@ async fn rocket() -> _ {
..rocket::Config::debug_default()
};
env_logger::init();
utils::start_up().await;
let _ = utils::start_up().await;
rocket::custom(&config)
.register(
"/",