mirror of
https://github.com/creating2morrow/neveko.git
synced 2025-01-03 09:29:39 +00:00
organize lmdb keys and order bug fix
This commit is contained in:
parent
4bff85e7f6
commit
c47ca7494e
13 changed files with 332 additions and 88 deletions
|
@ -32,7 +32,7 @@ use std::collections::BTreeMap;
|
|||
/// Create authorization data to sign and expiration
|
||||
pub fn create(address: &String) -> Authorization {
|
||||
info!("creating auth");
|
||||
let aid: String = format!("auth{}", utils::generate_rnd());
|
||||
let aid: String = format!("{}{}", crate::AUTH_DB_KEY, utils::generate_rnd());
|
||||
let rnd: String = utils::generate_rnd();
|
||||
let created: i64 = chrono::offset::Utc::now().timestamp();
|
||||
let token: String = create_token(String::from(address), created);
|
||||
|
|
|
@ -37,7 +37,7 @@ impl Prune {
|
|||
|
||||
/// Create a new contact
|
||||
pub async fn create(c: &Json<Contact>) -> Contact {
|
||||
let f_cid: String = format!("c{}", utils::generate_rnd());
|
||||
let f_cid: String = format!("{}{}", crate::CONTACT_DB_KEY, utils::generate_rnd());
|
||||
info!("creating contact: {}", f_cid);
|
||||
let new_contact = Contact {
|
||||
cid: String::from(&f_cid),
|
||||
|
@ -57,8 +57,8 @@ pub async fn create(c: &Json<Contact>) -> Contact {
|
|||
let k = &new_contact.cid;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Contact::to_db(&new_contact));
|
||||
// in order to retrieve all contact, write keys to with cl
|
||||
let list_key = format!("cl");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let list_key = crate::CONTACT_LIST_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating contact index");
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ pub fn find(cid: &String) -> Contact {
|
|||
/// All contact lookup
|
||||
pub fn find_all() -> Vec<Contact> {
|
||||
let s = db::Interface::open();
|
||||
let list_key = format!("cl");
|
||||
let list_key = crate::CONTACT_LIST_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
error!("contact index not found");
|
||||
|
|
|
@ -12,7 +12,7 @@ use rocket::serde::json::Json;
|
|||
|
||||
/// Create a new dispute
|
||||
pub fn create(d: Json<Dispute>) -> Dispute {
|
||||
let f_did: String = format!("dispute{}", utils::generate_rnd());
|
||||
let f_did: String = format!("{}{}", crate::DISPUTE_DB_KEY, utils::generate_rnd());
|
||||
info!("create dispute: {}", &f_did);
|
||||
let new_dispute = Dispute {
|
||||
did: String::from(&f_did),
|
||||
|
|
|
@ -15,6 +15,8 @@ use std::{
|
|||
process::Command,
|
||||
};
|
||||
|
||||
// TODO(c2m): remove this module and use monero public keys for text encryption
|
||||
|
||||
/// Searches for key, returns empty string if none exists
|
||||
///
|
||||
/// TODO(c2m): add more cli options
|
||||
|
|
|
@ -1,24 +1,43 @@
|
|||
pub mod args; // command line arguments
|
||||
pub mod auth; // internal auth repo/service layer
|
||||
pub mod contact; // contact repo/service layer
|
||||
pub mod dispute; // Dispute repo/service layer
|
||||
pub mod dispute; // dispute repo/service layer
|
||||
pub mod db; // lmdb interface
|
||||
pub mod gpg; // gpgme interface
|
||||
pub mod i2p; // i2p repo/service layer
|
||||
pub mod message; // message repo/service layer
|
||||
pub mod models; // db structs
|
||||
pub mod monero; // monero-wallet-rpc interface
|
||||
pub mod order; // Order repo/service layer
|
||||
pub mod product; // Product repo/service layer
|
||||
pub mod order; // order repo/service layer
|
||||
pub mod product; // product repo/service layer
|
||||
pub mod proof; // external auth/payment proof module
|
||||
pub mod reqres; // http request/responses
|
||||
pub mod user; // misc.
|
||||
pub mod utils; // user rep/service layer
|
||||
pub mod user; // user repo/service layer
|
||||
pub mod utils; // misc.
|
||||
|
||||
pub const APP_NAME: &str = "neveko";
|
||||
pub const NEVEKO_JWP_SECRET_KEY: &str = "NEVEKO_JWP_SECRET_KEY";
|
||||
pub const NEVEKO_JWT_SECRET_KEY: &str = "NEVEKO_JWT_SECRET_KEY";
|
||||
|
||||
// LMDB Keys
|
||||
pub const AUTH_DB_KEY: &str = "a";
|
||||
pub const CONTACT_DB_KEY: &str = "c";
|
||||
pub const DISPUTE_DB_KEY: &str = "d";
|
||||
pub const MESSAGE_DB_KEY: &str = "m";
|
||||
pub const ORDER_DB_KEY: &str = "o";
|
||||
pub const PRODUCT_DB_KEY: &str = "p";
|
||||
pub const USER_DB_KEY: &str = "u";
|
||||
pub const CONTACT_LIST_DB_KEY: &str = "cl";
|
||||
pub const MESSAGE_LIST_DB_KEY: &str = "ml";
|
||||
pub const ORDER_LIST_DB_KEY: &str = "ol";
|
||||
pub const PRODUCT_LIST_DB_KEY: &str = "pl";
|
||||
pub const RX_MESSAGE_DB_KEY: &str = "rx";
|
||||
pub const FTS_DB_KEY: &str = "fts";
|
||||
pub const CUSTOMER_ORDER_LIST_DB_KEY: &str = "olc";
|
||||
pub const MSIG_MESSAGE_DB_KEY: &str = "msig";
|
||||
pub const FTS_JWP_DB_KEY: &str = "fts-jwp";
|
||||
// End LMDB Keys
|
||||
|
||||
/// Environment variable for injecting wallet password
|
||||
pub const MONERO_WALLET_PASSWORD: &str = "MONERO_WALLET_PASSWORD";
|
||||
/// Environment variable for I2P proxy host
|
||||
|
|
|
@ -51,9 +51,9 @@ impl Default for MultisigMessageData {
|
|||
/// Create a new message
|
||||
pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Message {
|
||||
let rnd = utils::generate_rnd();
|
||||
let mut f_mid: String = format!("m{}", &rnd);
|
||||
let mut f_mid: String = format!("{}{}", crate::MESSAGE_DB_KEY, &rnd);
|
||||
if m_type == MessageType::Multisig {
|
||||
f_mid = format!("msig{}", &rnd);
|
||||
f_mid = format!("{}{}", crate::MSIG_MESSAGE_DB_KEY, &rnd);
|
||||
}
|
||||
info!("creating message: {}", &f_mid);
|
||||
let created = chrono::offset::Utc::now().timestamp();
|
||||
|
@ -73,8 +73,8 @@ pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Messa
|
|||
let k = &new_message.mid;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Message::to_db(&new_message));
|
||||
// in order to retrieve all message, write keys to with ml
|
||||
let list_key = format!("ml");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let list_key = crate::MESSAGE_LIST_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating message index");
|
||||
}
|
||||
|
@ -99,10 +99,10 @@ pub async fn rx(m: Json<Message>) {
|
|||
if !is_in_contact_list {
|
||||
return;
|
||||
}
|
||||
let f_mid: String = format!("m{}", utils::generate_rnd());
|
||||
let f_mid: String = format!("{}{}", crate::MESSAGE_DB_KEY, utils::generate_rnd());
|
||||
let new_message = Message {
|
||||
mid: String::from(&f_mid),
|
||||
uid: String::from("rx"),
|
||||
uid: String::from(crate::RX_MESSAGE_DB_KEY),
|
||||
from: String::from(&m.from),
|
||||
body: m.body.iter().cloned().collect(),
|
||||
created: chrono::offset::Utc::now().timestamp(),
|
||||
|
@ -113,8 +113,8 @@ pub async fn rx(m: Json<Message>) {
|
|||
let k = &new_message.mid;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Message::to_db(&new_message));
|
||||
// in order to retrieve all message, write keys to with rx
|
||||
let list_key = format!("rx");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let list_key = crate::RX_MESSAGE_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating message index");
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ pub async fn rx_multisig(m: Json<Message>) {
|
|||
let f_mid: String = format!("msig{}", utils::generate_rnd());
|
||||
let new_message = Message {
|
||||
mid: String::from(&f_mid),
|
||||
uid: String::from("rx"),
|
||||
uid: String::from(crate::RX_MESSAGE_DB_KEY),
|
||||
from: String::from(&m.from),
|
||||
body: m.body.iter().cloned().collect(),
|
||||
created: chrono::offset::Utc::now().timestamp(),
|
||||
|
@ -226,7 +226,7 @@ pub fn find(mid: &String) -> Message {
|
|||
/// Message lookup
|
||||
pub fn find_all() -> Vec<Message> {
|
||||
let i_s = db::Interface::open();
|
||||
let i_list_key = format!("ml");
|
||||
let i_list_key = crate::MESSAGE_LIST_DB_KEY;
|
||||
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
|
||||
if i_r == utils::empty_string() {
|
||||
error!("message index not found");
|
||||
|
@ -240,7 +240,7 @@ pub fn find_all() -> Vec<Message> {
|
|||
messages.push(message);
|
||||
}
|
||||
}
|
||||
let o_list_key = format!("rx");
|
||||
let o_list_key = crate::RX_MESSAGE_DB_KEY;
|
||||
let o_s = db::Interface::open();
|
||||
let o_r = db::Interface::read(&o_s.env, &o_s.handle, &String::from(o_list_key));
|
||||
if o_r == utils::empty_string() {
|
||||
|
@ -350,8 +350,8 @@ async fn send_to_retry(mid: String) {
|
|||
info!("sending {} to fts", &mid);
|
||||
let s = db::Interface::open();
|
||||
// in order to retrieve FTS (failed-to-send), write keys to db with fts
|
||||
let list_key = format!("fts");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let list_key = crate::FTS_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating fts message index");
|
||||
}
|
||||
|
@ -366,8 +366,7 @@ async fn send_to_retry(mid: String) {
|
|||
);
|
||||
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
|
||||
// restart fts if not empty
|
||||
let list_key = format!("fts");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
let v_mid = r.split(",");
|
||||
let v: Vec<String> = v_mid.map(|s| String::from(s)).collect();
|
||||
debug!("fts contents: {:#?}", v);
|
||||
|
@ -383,8 +382,8 @@ fn remove_from_fts(mid: String) {
|
|||
info!("removing id {} from fts", &mid);
|
||||
let s = db::Interface::open();
|
||||
// in order to retrieve FTS (failed-to-send), write keys to with fts
|
||||
let list_key = format!("fts");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let list_key = crate::FTS_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("fts is empty");
|
||||
}
|
||||
|
@ -417,7 +416,7 @@ pub async fn retry_fts() {
|
|||
debug!("running retry failed-to-send thread");
|
||||
tick.recv().unwrap();
|
||||
let s = db::Interface::open();
|
||||
let list_key = format!("fts");
|
||||
let list_key = crate::FTS_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
info!("fts message index not found");
|
||||
|
@ -430,7 +429,7 @@ pub async fn retry_fts() {
|
|||
if cleared {
|
||||
// index was created but cleared
|
||||
info!("terminating retry fts thread");
|
||||
db::Interface::delete(&s.env, &s.handle, "fts");
|
||||
db::Interface::delete(&s.env, &s.handle, list_key);
|
||||
break;
|
||||
}
|
||||
for m in v {
|
||||
|
@ -438,7 +437,7 @@ pub async fn retry_fts() {
|
|||
if message.mid != utils::empty_string() {
|
||||
let s = db::Interface::open();
|
||||
// get jwp from db
|
||||
let k = format!("{}-{}", "fts-jwp", &message.to);
|
||||
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &message.to);
|
||||
let jwp = db::Interface::read(&s.env, &s.handle, &k);
|
||||
if jwp != utils::empty_string() {
|
||||
let m_type = if message.mid.contains("misg") {
|
||||
|
@ -479,7 +478,7 @@ pub async fn send_prepare_info(orid: &String, contact: &String) {
|
|||
let wallet_password = utils::empty_string();
|
||||
monero::open_wallet(&orid, &wallet_password).await;
|
||||
let prepare_info = monero::prepare_wallet().await;
|
||||
let k = format!("{}-{}", "fts-jwp", contact);
|
||||
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
|
||||
let jwp = db::Interface::read(&s.env, &s.handle, &k);
|
||||
let body_str = format!(
|
||||
"{}:{}:{}",
|
||||
|
@ -504,7 +503,7 @@ pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>)
|
|||
let wallet_password = utils::empty_string();
|
||||
monero::open_wallet(&orid, &wallet_password).await;
|
||||
let make_info = monero::make_wallet(info).await;
|
||||
let k = format!("{}-{}", "fts-jwp", contact);
|
||||
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
|
||||
let jwp = db::Interface::read(&s.env, &s.handle, &k);
|
||||
let body_str = format!("{}:{}:{}", MAKE_MSIG, orid, &make_info.result.multisig_info);
|
||||
let message: Message = Message {
|
||||
|
@ -526,7 +525,7 @@ pub async fn send_exchange_info(orid: &String, contact: &String, info: Vec<Strin
|
|||
let wallet_password = utils::empty_string();
|
||||
monero::open_wallet(&orid, &wallet_password).await;
|
||||
let exchange_info = monero::exchange_multisig_keys(false, info, &wallet_password).await;
|
||||
let k = format!("{}-{}", "fts-jwp", contact);
|
||||
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
|
||||
let jwp = db::Interface::read(&s.env, &s.handle, &k);
|
||||
let body_str = format!(
|
||||
"{}:{}:{}",
|
||||
|
@ -551,7 +550,7 @@ pub async fn send_export_info(orid: &String, contact: &String) {
|
|||
let wallet_password = utils::empty_string();
|
||||
monero::open_wallet(&orid, &wallet_password).await;
|
||||
let exchange_info = monero::export_multisig_info().await;
|
||||
let k = format!("{}-{}", "fts-jwp", contact);
|
||||
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, contact);
|
||||
let jwp = db::Interface::read(&s.env, &s.handle, &k);
|
||||
let body_str = format!("{}:{}:{}", EXPORT_MSIG, orid, &exchange_info.result.info);
|
||||
let message: Message = Message {
|
||||
|
|
|
@ -20,6 +20,7 @@ use log::{
|
|||
use rocket::serde::json::Json;
|
||||
|
||||
enum StatusType {
|
||||
_Cancelled,
|
||||
Delivered,
|
||||
MultisigMissing,
|
||||
MulitsigComplete,
|
||||
|
@ -29,6 +30,7 @@ enum StatusType {
|
|||
impl StatusType {
|
||||
pub fn value(&self) -> String {
|
||||
match *self {
|
||||
StatusType::_Cancelled => String::from("Cancelled"),
|
||||
StatusType::Delivered => String::from("Delivered"),
|
||||
StatusType::MultisigMissing => String::from("MultisigMissing"),
|
||||
StatusType::MulitsigComplete => String::from("MulitsigComplete"),
|
||||
|
@ -45,7 +47,7 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Order {
|
|||
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||
let ts = chrono::offset::Utc::now().timestamp();
|
||||
let orid: String = format!("O{}", utils::generate_rnd());
|
||||
let orid: String = format!("{}{}", crate::ORDER_DB_KEY, utils::generate_rnd());
|
||||
let r_subaddress = monero::create_address().await;
|
||||
let subaddress = r_subaddress.result.address;
|
||||
let new_order = Order {
|
||||
|
@ -71,8 +73,8 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Order {
|
|||
let k = &new_order.orid;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Order::to_db(&new_order));
|
||||
// in order to retrieve all orders, write keys to with ol
|
||||
let list_key = format!("ol");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let list_key = crate::ORDER_LIST_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating order index");
|
||||
}
|
||||
|
@ -83,6 +85,23 @@ pub async fn create(j_order: Json<reqres::OrderRequest>) -> Order {
|
|||
new_order
|
||||
}
|
||||
|
||||
/// Backup order for customer
|
||||
pub fn backup(order: &Order) {
|
||||
info!("creating backup of order: {}", order.orid);
|
||||
let s = db::Interface::open();
|
||||
let k = &order.orid;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Order::to_db(&order));
|
||||
// in order to retrieve all orders, write keys to with col
|
||||
let list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating customer order index");
|
||||
}
|
||||
let order_list = [r, String::from(&order.orid)].join(",");
|
||||
debug!("writing order index {} for id: {}", order_list, list_key);
|
||||
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &order_list);
|
||||
}
|
||||
|
||||
/// Lookup order
|
||||
pub fn find(oid: &String) -> Order {
|
||||
info!("find order: {}", &oid);
|
||||
|
@ -98,7 +117,7 @@ pub fn find(oid: &String) -> Order {
|
|||
/// Lookup all orders from admin server
|
||||
pub fn find_all() -> Vec<Order> {
|
||||
let i_s = db::Interface::open();
|
||||
let i_list_key = format!("ol");
|
||||
let i_list_key = crate::ORDER_LIST_DB_KEY;
|
||||
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
|
||||
if i_r == utils::empty_string() {
|
||||
error!("order index not found");
|
||||
|
@ -115,11 +134,31 @@ pub fn find_all() -> Vec<Order> {
|
|||
orders
|
||||
}
|
||||
|
||||
/// Lookup all orders that customer has saved from gui
|
||||
pub fn find_all_backup() -> Vec<Order> {
|
||||
let i_s = db::Interface::open();
|
||||
let i_list_key = crate::CUSTOMER_ORDER_LIST_DB_KEY;
|
||||
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
|
||||
if i_r == utils::empty_string() {
|
||||
error!("customer order index not found");
|
||||
}
|
||||
let i_v_oid = i_r.split(",");
|
||||
let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect();
|
||||
let mut orders: Vec<Order> = Vec::new();
|
||||
for o in i_v {
|
||||
let order: Order = find(&o);
|
||||
if order.orid != utils::empty_string() {
|
||||
orders.push(order);
|
||||
}
|
||||
}
|
||||
orders
|
||||
}
|
||||
|
||||
/// Lookup all orders for customer
|
||||
pub async fn find_all_customer_orders(cid: String) -> Vec<Order> {
|
||||
info!("lookup orders for customer: {}", &cid);
|
||||
let i_s = db::Interface::open();
|
||||
let i_list_key = format!("ol");
|
||||
let i_list_key = crate::ORDER_LIST_DB_KEY;
|
||||
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
|
||||
if i_r == utils::empty_string() {
|
||||
error!("order index not found");
|
||||
|
@ -298,7 +337,11 @@ pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
|
|||
}
|
||||
|
||||
/// Send order request to vendor and start multisig flow
|
||||
pub async fn transmit_order_request(contact: String, jwp: String, request: reqres::OrderRequest) -> Result<Order, Box<dyn Error>> {
|
||||
pub async fn transmit_order_request(
|
||||
contact: String,
|
||||
jwp: String,
|
||||
request: reqres::OrderRequest,
|
||||
) -> Result<Order, Box<dyn Error>> {
|
||||
let host = utils::get_i2p_http_proxy();
|
||||
let proxy = reqwest::Proxy::http(&host)?;
|
||||
let client = reqwest::Client::builder().proxy(proxy).build();
|
||||
|
@ -313,7 +356,7 @@ pub async fn transmit_order_request(contact: String, jwp: String, request: reqre
|
|||
let res = response.json::<Order>().await;
|
||||
debug!("create order response: {:?}", res);
|
||||
match res {
|
||||
Ok(_r) => Ok(Default::default()),
|
||||
Ok(r) => Ok(r),
|
||||
_ => Ok(Default::default()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::error::Error;
|
|||
|
||||
/// Create a new product
|
||||
pub fn create(d: Json<Product>) -> Product {
|
||||
let pid: String = format!("product{}", utils::generate_rnd());
|
||||
let pid: String = format!("{}{}", crate::PRODUCT_DB_KEY, utils::generate_rnd());
|
||||
if !validate_product(&d) {
|
||||
error!("invalid product");
|
||||
return Default::default();
|
||||
|
@ -33,8 +33,8 @@ pub fn create(d: Json<Product>) -> Product {
|
|||
let k = &new_product.pid;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Product::to_db(&new_product));
|
||||
// in order to retrieve all products, write keys to with pl
|
||||
let list_key = format!("pl");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
let list_key = crate::PRODUCT_LIST_DB_KEY;
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating product index");
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ pub fn find(pid: &String) -> Product {
|
|||
/// Product lookup for all
|
||||
pub fn find_all() -> Vec<Product> {
|
||||
let i_s = db::Interface::open();
|
||||
let i_list_key = format!("pl");
|
||||
let i_list_key = crate::PRODUCT_LIST_DB_KEY;
|
||||
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
|
||||
if i_r == utils::empty_string() {
|
||||
error!("product index not found");
|
||||
|
|
|
@ -133,7 +133,7 @@ pub async fn prove_payment(contact: String, txp: &TxProof) -> Result<reqres::Jwp
|
|||
Ok(r) => {
|
||||
// cache the jwp for for fts
|
||||
let s = db::Interface::open();
|
||||
let k = format!("{}-{}", "fts-jwp", &contact);
|
||||
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
|
||||
db::Interface::delete(&s.env, &s.handle, &k);
|
||||
db::Interface::write(&s.env, &s.handle, &k, &r.jwp);
|
||||
Ok(r)
|
||||
|
|
|
@ -12,10 +12,12 @@ use log::{
|
|||
use rocket::serde::json::Json;
|
||||
|
||||
// This module is only used for remote access
|
||||
// TODO(c2m): remove this module since there is only support for a single
|
||||
// authenticated user
|
||||
|
||||
/// Create a new user
|
||||
pub fn create(address: &String) -> User {
|
||||
let f_uid: String = format!("u{}", utils::generate_rnd());
|
||||
let f_uid: String = format!("{}{}", crate::USER_DB_KEY, utils::generate_rnd());
|
||||
let new_user = User {
|
||||
uid: String::from(&f_uid),
|
||||
xmr_address: String::from(address),
|
||||
|
|
|
@ -336,9 +336,9 @@ impl eframe::App for AddressBookApp {
|
|||
if ui.button("Sign Key").clicked() {
|
||||
contact::trust_gpg(self.status.i2p.clone());
|
||||
utils::write_gui_db(
|
||||
String::from("gui-signed-key"),
|
||||
String::from(crate::GUI_SIGNED_GPG_DB_KEY),
|
||||
self.status.i2p.clone(),
|
||||
String::from("1"),
|
||||
String::from(crate::SIGNED_GPG_KEY),
|
||||
);
|
||||
self.showing_status = false;
|
||||
}
|
||||
|
@ -542,7 +542,7 @@ impl eframe::App for AddressBookApp {
|
|||
row.col(|ui| {
|
||||
if ui.button("Check Status").clicked() {
|
||||
let nick_db = utils::search_gui_db(
|
||||
String::from("gui-nick"),
|
||||
String::from(crate::GUI_NICK_DB_KEY),
|
||||
String::from(&c.i2p_address),
|
||||
);
|
||||
let nick = if nick_db == utils::empty_string() {
|
||||
|
@ -554,16 +554,16 @@ impl eframe::App for AddressBookApp {
|
|||
self.status.i2p = String::from(&c.i2p_address);
|
||||
// get the txp
|
||||
self.status.txp = utils::search_gui_db(
|
||||
String::from("gui-txp"),
|
||||
String::from(crate::GUI_TX_PROOF_DB_KEY),
|
||||
String::from(&c.i2p_address),
|
||||
);
|
||||
// get the jwp
|
||||
self.status.jwp = utils::search_gui_db(
|
||||
String::from("gui-jwp"),
|
||||
String::from(crate::GUI_JWP_DB_KEY),
|
||||
String::from(&c.i2p_address),
|
||||
);
|
||||
let r_exp = utils::search_gui_db(
|
||||
String::from("gui-exp"),
|
||||
String::from(crate::GUI_EXP_DB_KEY),
|
||||
String::from(&c.i2p_address),
|
||||
);
|
||||
self.status.exp = r_exp;
|
||||
|
@ -713,22 +713,22 @@ fn send_payment_req(
|
|||
signature: get_txp.result.signature,
|
||||
};
|
||||
utils::write_gui_db(
|
||||
String::from("gui-txp"),
|
||||
String::from(crate::GUI_TX_PROOF_DB_KEY),
|
||||
String::from(&contact),
|
||||
String::from(&ftxp.signature),
|
||||
);
|
||||
utils::write_gui_db(
|
||||
String::from("gui-txp-hash"),
|
||||
String::from(crate::GUI_TX_HASH_DB_KEY),
|
||||
String::from(&contact),
|
||||
String::from(&ftxp.hash),
|
||||
);
|
||||
utils::write_gui_db(
|
||||
String::from("gui-txp-sig"),
|
||||
String::from(crate::GUI_TX_SIGNATURE_DB_KEY),
|
||||
String::from(&contact),
|
||||
String::from(&ftxp.signature),
|
||||
);
|
||||
utils::write_gui_db(
|
||||
String::from("gui-txp-subaddress"),
|
||||
String::from(crate::GUI_TX_SUBADDRESS_DB_KEY),
|
||||
String::from(&contact),
|
||||
String::from(&ftxp.subaddress),
|
||||
);
|
||||
|
@ -746,7 +746,7 @@ fn send_payment_req(
|
|||
match proof::prove_payment(String::from(&contact), &ftxp).await {
|
||||
Ok(result) => {
|
||||
utils::write_gui_db(
|
||||
String::from("gui-jwp"),
|
||||
String::from(crate::GUI_JWP_DB_KEY),
|
||||
String::from(&contact),
|
||||
String::from(&result.jwp),
|
||||
);
|
||||
|
@ -754,7 +754,7 @@ fn send_payment_req(
|
|||
let seconds: i64 = expire as i64 * 2 * 60;
|
||||
let unix: i64 = chrono::offset::Utc::now().timestamp() + seconds;
|
||||
utils::write_gui_db(
|
||||
String::from("gui-exp"),
|
||||
String::from(crate::GUI_EXP_DB_KEY),
|
||||
String::from(&contact),
|
||||
format!("{}", unix),
|
||||
);
|
||||
|
@ -767,9 +767,9 @@ fn send_payment_req(
|
|||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||
}
|
||||
if retry {
|
||||
let k_hash = String::from("gui-txp-hash");
|
||||
let k_sig = String::from("gui-txp-sig");
|
||||
let k_subaddress = String::from("gui-txp-subaddress");
|
||||
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));
|
||||
|
@ -788,7 +788,7 @@ fn send_payment_req(
|
|||
match proof::prove_payment(String::from(&contact), &ftxp).await {
|
||||
Ok(result) => {
|
||||
utils::write_gui_db(
|
||||
String::from("gui-jwp"),
|
||||
String::from(crate::GUI_JWP_DB_KEY),
|
||||
String::from(&contact),
|
||||
String::from(&result.jwp),
|
||||
);
|
||||
|
@ -825,14 +825,18 @@ fn send_message_req(tx: Sender<bool>, ctx: egui::Context, body: String, to: Stri
|
|||
}
|
||||
|
||||
fn check_signed_key(contact: String) -> bool {
|
||||
let v = utils::search_gui_db(String::from("gui-signed-key"), contact);
|
||||
let v = utils::search_gui_db(String::from(crate::GUI_SIGNED_GPG_DB_KEY), contact);
|
||||
v != utils::empty_string()
|
||||
}
|
||||
|
||||
fn change_nick_req(contact: String, nick: String) {
|
||||
log::debug!("change nick");
|
||||
utils::clear_gui_db(String::from("gui-nick"), String::from(&contact));
|
||||
utils::write_gui_db(String::from("gui-nick"), String::from(&contact), nick);
|
||||
utils::clear_gui_db(String::from(crate::GUI_NICK_DB_KEY), String::from(&contact));
|
||||
utils::write_gui_db(
|
||||
String::from(crate::GUI_NICK_DB_KEY),
|
||||
String::from(&contact),
|
||||
nick,
|
||||
);
|
||||
}
|
||||
|
||||
fn send_can_transfer_req(tx: Sender<bool>, ctx: egui::Context, invoice: u128) {
|
||||
|
|
|
@ -9,6 +9,7 @@ pub struct MarketApp {
|
|||
contact_info_rx: Receiver<models::Contact>,
|
||||
contact_timeout_tx: Sender<bool>,
|
||||
contact_timeout_rx: Receiver<bool>,
|
||||
customer_orders: Vec<models::Order>,
|
||||
find_vendor: String,
|
||||
get_vendor_products_tx: Sender<Vec<models::Product>>,
|
||||
get_vendor_products_rx: Receiver<Vec<models::Product>>,
|
||||
|
@ -17,6 +18,8 @@ pub struct MarketApp {
|
|||
is_loading: bool,
|
||||
is_ordering: bool,
|
||||
is_pinging: bool,
|
||||
is_customer_viewing_orders: bool,
|
||||
is_managing_multisig: bool,
|
||||
is_product_image_set: bool,
|
||||
is_showing_products: bool,
|
||||
is_showing_product_image: bool,
|
||||
|
@ -69,12 +72,15 @@ impl Default for MarketApp {
|
|||
contact_info_tx,
|
||||
contact_timeout_rx,
|
||||
contact_timeout_tx,
|
||||
customer_orders: Vec::new(),
|
||||
find_vendor: utils::empty_string(),
|
||||
get_vendor_products_rx,
|
||||
get_vendor_products_tx,
|
||||
get_vendor_product_rx,
|
||||
get_vendor_product_tx,
|
||||
is_customer_viewing_orders: false,
|
||||
is_loading: false,
|
||||
is_managing_multisig: false,
|
||||
is_ordering: false,
|
||||
is_pinging: false,
|
||||
is_product_image_set: false,
|
||||
|
@ -185,6 +191,152 @@ impl eframe::App for MarketApp {
|
|||
}
|
||||
}
|
||||
|
||||
// Vendor status window
|
||||
//-----------------------------------------------------------------------------------
|
||||
let mut is_showing_vendor_status = self.is_showing_vendor_status;
|
||||
egui::Window::new(&self.vendor_status.i2p)
|
||||
.open(&mut is_showing_vendor_status)
|
||||
.vscroll(true)
|
||||
.title_bar(false)
|
||||
.id(egui::Id::new(self.vendor_status.i2p.clone()))
|
||||
.show(&ctx, |ui| {
|
||||
if self.is_pinging {
|
||||
ui.add(egui::Spinner::new());
|
||||
ui.label("pinging...");
|
||||
}
|
||||
let status = if self.s_contact.xmr_address != utils::empty_string() {
|
||||
"online"
|
||||
} else {
|
||||
"offline"
|
||||
};
|
||||
let mode = if self.vendor_status.is_vendor {
|
||||
"enabled "
|
||||
} else {
|
||||
"disabled"
|
||||
};
|
||||
ui.label(format!("status: {}", status));
|
||||
ui.label(format!("vendor mode: {}", mode));
|
||||
ui.label(format!("nick: {}", self.vendor_status.nick));
|
||||
ui.label(format!("tx proof: {}", self.vendor_status.txp));
|
||||
ui.label(format!("jwp: {}", self.vendor_status.jwp));
|
||||
ui.label(format!("expiration: {}", self.vendor_status.h_exp));
|
||||
ui.label(format!("signed key: {}", self.vendor_status.signed_key));
|
||||
if ui.button("Exit").clicked() {
|
||||
self.is_showing_vendor_status = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Product image window
|
||||
//-----------------------------------------------------------------------------------
|
||||
let mut is_showing_product_image = self.is_showing_product_image;
|
||||
egui::Window::new("")
|
||||
.open(&mut is_showing_product_image)
|
||||
.vscroll(true)
|
||||
.show(ctx, |ui| {
|
||||
self.product_image.show(ui);
|
||||
if ui.button("Exit").clicked() {
|
||||
self.is_showing_product_image = false;
|
||||
self.is_product_image_set = false;
|
||||
let read_product_image = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
|
||||
self.product_image =
|
||||
egui_extras::RetainedImage::from_image_bytes("qr.png", &read_product_image)
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
// Multisig Management window
|
||||
//-----------------------------------------------------------------------------------
|
||||
let mut is_managing_multisig = self.is_managing_multisig;
|
||||
egui::Window::new("Multisig Management")
|
||||
.open(&mut is_managing_multisig)
|
||||
.vscroll(true)
|
||||
.show(ctx, |ui| {
|
||||
// TODO(c2m): interactive multisig checklist
|
||||
if ui.button("Exit").clicked() {
|
||||
self.is_managing_multisig = false;
|
||||
self.is_loading = false;
|
||||
}
|
||||
});
|
||||
|
||||
// View orders - Customer Order Flow Management
|
||||
//-----------------------------------------------------------------------------------
|
||||
let mut is_customer_viewing_orders = self.is_customer_viewing_orders;
|
||||
egui::Window::new("View Orders")
|
||||
.open(&mut is_customer_viewing_orders)
|
||||
.vscroll(true)
|
||||
.show(&ctx, |ui| {
|
||||
use egui_extras::{
|
||||
Column,
|
||||
TableBuilder,
|
||||
};
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.resizable(true)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.min_scrolled_height(0.0);
|
||||
|
||||
table
|
||||
.header(20.0, |mut header| {
|
||||
header.col(|ui| {
|
||||
ui.strong("orid");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("date");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("status");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("");
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
for o in &self.customer_orders {
|
||||
let row_height = 20.0;
|
||||
body.row(row_height, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label(format!("{}", o.orid));
|
||||
});
|
||||
row.col(|ui| {
|
||||
let h_date =
|
||||
chrono::NaiveDateTime::from_timestamp_opt(o.date, 0)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
ui.label(format!("{}", h_date));
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(format!("{}", o.status));
|
||||
});
|
||||
row.col(|ui| {
|
||||
if ui.button("MSIG").clicked() {
|
||||
// dynamically generate buttons for multisig wallet ops
|
||||
}
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.style_mut().wrap = Some(false);
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Cancel").clicked() {
|
||||
// TODO(c2m): Cancel order logic
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
if ui.button("Exit").clicked() {
|
||||
self.is_customer_viewing_orders = false;
|
||||
self.is_loading = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Customer Order Form
|
||||
//-----------------------------------------------------------------------------------
|
||||
let mut is_ordering = self.is_ordering;
|
||||
|
@ -192,6 +344,10 @@ impl eframe::App for MarketApp {
|
|||
.open(&mut is_ordering)
|
||||
.vscroll(true)
|
||||
.show(&ctx, |ui| {
|
||||
if self.is_loading {
|
||||
ui.add(egui::Spinner::new());
|
||||
ui.label("loading...");
|
||||
}
|
||||
ui.label(format!("cid: {}", self.new_order.cid));
|
||||
ui.label(format!("pid: {}", self.new_order.pid));
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -200,7 +356,7 @@ impl eframe::App for MarketApp {
|
|||
.labelled_by(shipping_name.id);
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
let qty_name = ui.label("quantity: \t\t");
|
||||
let qty_name = ui.label("quantity: \t\t\t\t");
|
||||
ui.text_edit_singleline(&mut self.new_order_quantity)
|
||||
.labelled_by(qty_name.id);
|
||||
});
|
||||
|
@ -235,13 +391,12 @@ impl eframe::App for MarketApp {
|
|||
self.vendor_status.i2p.clone(),
|
||||
ctx.clone(),
|
||||
self.vendor_status.jwp.clone(),
|
||||
new_order
|
||||
new_order,
|
||||
);
|
||||
self.new_order = Default::default();
|
||||
self.new_order_price = 0;
|
||||
self.new_order_quantity = utils::empty_string();
|
||||
self.new_order_shipping_address = utils::empty_string();
|
||||
self.is_ordering = false;
|
||||
self.is_showing_products = false;
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +468,7 @@ impl eframe::App for MarketApp {
|
|||
row.col(|ui| {
|
||||
if ui.button("Check Status").clicked() {
|
||||
let nick_db = utils::search_gui_db(
|
||||
String::from("gui-nick"),
|
||||
String::from(crate::GUI_NICK_DB_KEY),
|
||||
String::from(&v.i2p_address),
|
||||
);
|
||||
let nick = if nick_db == utils::empty_string() {
|
||||
|
@ -325,17 +480,16 @@ impl eframe::App for MarketApp {
|
|||
self.vendor_status.i2p = String::from(&v.i2p_address);
|
||||
// get the txp
|
||||
self.vendor_status.txp = utils::search_gui_db(
|
||||
String::from("gui-txp"),
|
||||
String::from(crate::GUI_TX_PROOF_DB_KEY),
|
||||
String::from(&v.i2p_address),
|
||||
);
|
||||
// get the jwp
|
||||
self.vendor_status.jwp = utils::search_gui_db(
|
||||
String::from("gui-jwp"),
|
||||
String::from(crate::GUI_JWP_DB_KEY),
|
||||
String::from(&v.i2p_address),
|
||||
);
|
||||
log::debug!("jwp: {}", self.vendor_status.jwp);
|
||||
let r_exp = utils::search_gui_db(
|
||||
String::from("gui-exp"),
|
||||
String::from(crate::GUI_EXP_DB_KEY),
|
||||
String::from(&v.i2p_address),
|
||||
);
|
||||
self.vendor_status.exp = r_exp;
|
||||
|
@ -686,10 +840,10 @@ impl eframe::App for MarketApp {
|
|||
}
|
||||
});
|
||||
|
||||
// TODO(c2m): Orders window
|
||||
// Vendor Orders window
|
||||
//-----------------------------------------------------------------------------------
|
||||
let mut is_showing_orders = self.is_showing_orders;
|
||||
egui::Window::new("Orders")
|
||||
egui::Window::new("Manage Orders")
|
||||
.open(&mut is_showing_orders)
|
||||
.vscroll(true)
|
||||
.show(&ctx, |ui| {
|
||||
|
@ -781,7 +935,8 @@ impl eframe::App for MarketApp {
|
|||
}
|
||||
ui.label("\n");
|
||||
if ui.button("View Orders").clicked() {
|
||||
// TODO(c2m):
|
||||
self.customer_orders = order::find_all_backup();
|
||||
self.is_customer_viewing_orders = true;
|
||||
}
|
||||
if self.is_vendor_enabled {
|
||||
ui.label("\n");
|
||||
|
@ -850,6 +1005,10 @@ impl eframe::App for MarketApp {
|
|||
self.is_showing_products = true;
|
||||
self.is_showing_vendors = false;
|
||||
}
|
||||
ui.label("\n");
|
||||
if ui.button("Manage Orders").clicked() {
|
||||
// TODO(c2m): vendor order management logic
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -884,7 +1043,7 @@ fn send_contact_info_req(
|
|||
}
|
||||
|
||||
fn check_signed_key(contact: String) -> bool {
|
||||
let v = utils::search_gui_db(String::from("gui-signed-key"), contact);
|
||||
let v = utils::search_gui_db(String::from(crate::GUI_SIGNED_GPG_DB_KEY), contact);
|
||||
v != utils::empty_string()
|
||||
}
|
||||
|
||||
|
@ -937,18 +1096,20 @@ fn vendor_status_timeout(tx: Sender<bool>, ctx: egui::Context) {
|
|||
});
|
||||
}
|
||||
|
||||
fn submit_order_req(tx: Sender<models::Order>, contact: String, ctx: egui::Context, jwp: String, request: reqres::OrderRequest) {
|
||||
fn submit_order_req(
|
||||
tx: Sender<models::Order>,
|
||||
contact: String,
|
||||
ctx: egui::Context,
|
||||
jwp: String,
|
||||
request: reqres::OrderRequest,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
log::info!("submit order");
|
||||
let r_contact = String::from(&contact);
|
||||
let order = order::transmit_order_request(r_contact, jwp, request).await;
|
||||
let u_order = order.unwrap_or(Default::default());
|
||||
let u_order = order.unwrap_or_else(|_| Default::default());
|
||||
// cache order request to db
|
||||
utils::write_gui_db(
|
||||
String::from("gui-orid"),
|
||||
String::from(&contact),
|
||||
String::from(&u_order.orid),
|
||||
);
|
||||
order::backup(&u_order);
|
||||
let _ = tx.send(u_order);
|
||||
ctx.request_repaint();
|
||||
});
|
||||
|
|
|
@ -5,6 +5,20 @@ mod apps;
|
|||
mod login;
|
||||
mod wrap_app;
|
||||
|
||||
// LMDB keys
|
||||
pub const GUI_JWP_DB_KEY: &str = "gui-jwp";
|
||||
pub const GUI_EXP_DB_KEY: &str = "gui-exp";
|
||||
pub const GUI_TX_PROOF_DB_KEY: &str = "gui-txp";
|
||||
pub const GUI_NICK_DB_KEY: &str = "gui-nick";
|
||||
pub const GUI_TX_SIGNATURE_DB_KEY: &str = "gui-txp-sig";
|
||||
pub const GUI_TX_HASH_DB_KEY: &str = "gui-txp-hash";
|
||||
pub const GUI_SIGNED_GPG_DB_KEY: &str = "gui-signed-key";
|
||||
pub const GUI_TX_SUBADDRESS_DB_KEY: &str = "gui-txp-subaddress";
|
||||
// End LMDB keys
|
||||
|
||||
/// Designate a contact as verified and trusted
|
||||
pub const SIGNED_GPG_KEY: &str = "1";
|
||||
|
||||
/// key for fetching the login credential hash
|
||||
pub const CREDENTIAL_KEY: &str = "NEVEKO_GUI_KEY";
|
||||
/// TODO(c2m): configurable lock screen timeout
|
||||
|
|
Loading…
Reference in a new issue