allow setting wallet password on initial startup

This commit is contained in:
creating2morrow 2023-05-28 21:12:31 -04:00
parent a2fa0bf384
commit e3d62b1edc
5 changed files with 523 additions and 14 deletions

View file

@ -15,6 +15,10 @@ pub mod utils; // user rep/service layer
pub const NEVMES_JWP_SECRET_KEY: &str = "NEVMES_JWP_SECRET_KEY";
pub const NEVMES_JWT_SECRET_KEY: &str = "NEVMES_JWT_SECRET_KEY";
// TODO(c2m): better handling of setting initial wallet password
/// Environment variable for injecting wallet password
pub const MONERO_WALLET_PASSWORD: &str = "MONERO_WALLET_PASSWORD";
/// The latest monero release download
pub const MONERO_RELEASE_VERSION: &str = "monero-linux-x64-v0.18.2.2.tar.bz2";
pub const MONERO_RELEASE_HASH: &str =

View file

@ -216,3 +216,193 @@ impl User {
}
}
}
#[derive(Debug, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Product {
pub pid: String,
pub vid: String,
pub in_stock: bool,
pub description: String,
pub name: String,
pub price: i64,
pub qty: i64,
}
impl Default for Product {
fn default() -> Self {
Product {
pid: utils::empty_string(),
vid: utils::empty_string(),
description: utils::empty_string(),
in_stock: false,
name: utils::empty_string(),
price: 0,
qty: 0,
}
}
}
impl Product {
pub fn to_db(p: &Product) -> String {
format!(
"{}:{}:{}:{}:{}:{}",
p.vid, p.description, p.in_stock, p.name, p.price, p.qty
)
}
pub fn from_db(k: String, v: String) -> Product {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let vid = v.remove(0);
let description = v.remove(0);
let in_stock = match v.remove(0).parse::<bool>() {
Ok(b) => b,
Err(_) => false,
};
let name = v.remove(0);
let price = match v.remove(0).parse::<i64>() {
Ok(p) => p,
Err(_) => 0,
};
let qty = match v.remove(0).parse::<i64>() {
Ok(q) => q,
Err(_) => 0,
};
Product {
pid: k,
vid,
description,
in_stock,
name,
price,
qty,
}
}
pub fn update(
p: Product,
description: String,
in_stock: bool,
name: String,
price: i64,
qty: i64,
) -> Product {
Product {
pid: p.pid,
vid: p.vid,
description,
in_stock,
name,
price,
qty,
}
}
}
// TODO: add mediator fields
#[derive(Debug)]
pub struct Order {
pub orid: String,
pub c_id: String,
pub p_id: String,
pub v_id: String,
pub xmr_address: String,
pub cust_msig_info: String,
pub cust_msig_txset: String,
pub cust_kex_1: String,
pub cust_kex_2: String,
pub cust_kex_3: String,
pub date: i64,
pub deliver_date: i64,
pub ship_date: i64,
pub hash: String,
pub msig_prepare: String,
pub msig_make: String,
pub msig_kex_1: String,
pub msig_kex_2: String,
pub msig_kex_3: String,
pub subaddress: String,
pub status: String,
pub quantity: i64,
pub vend_kex_1: String,
pub vend_kex_2: String,
pub vend_kex_3: String,
pub vend_msig_info: String,
pub vend_msig_txset: String,
}
impl Default for Order {
fn default() -> Self {
Order {
orid: utils::empty_string(),
c_id: utils::empty_string(),
p_id: utils::empty_string(),
v_id: utils::empty_string(),
xmr_address: utils::empty_string(),
cust_msig_info: utils::empty_string(),
cust_msig_txset: utils::empty_string(),
cust_kex_1: utils::empty_string(),
cust_kex_2: utils::empty_string(),
cust_kex_3: utils::empty_string(),
date: 0,
deliver_date: 0,
ship_date: 0,
hash: utils::empty_string(),
msig_prepare: utils::empty_string(),
msig_make: utils::empty_string(),
msig_kex_1: utils::empty_string(),
msig_kex_2: utils::empty_string(),
msig_kex_3: utils::empty_string(),
subaddress: utils::empty_string(),
status: utils::empty_string(),
quantity: 0,
vend_kex_1: utils::empty_string(),
vend_kex_2: utils::empty_string(),
vend_kex_3: utils::empty_string(),
vend_msig_info: utils::empty_string(),
vend_msig_txset: utils::empty_string(),
}
}
}
#[derive(Debug, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Dispute {
pub did: String,
pub created: i64,
pub orid: String,
pub tx_set: String,
}
impl Default for Dispute {
fn default() -> Self {
Dispute {
did: utils::empty_string(),
created: 0,
orid: utils::empty_string(),
tx_set: utils::empty_string(),
}
}
}
impl Dispute {
pub fn to_db(d: &Dispute) -> String {
format!("{}:{}:{}", d.created, d.orid, d.tx_set)
}
pub fn from_db(k: String, v: String) -> Dispute {
let values = v.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let created = match v.remove(0).parse::<i64>() {
Ok(t) => t,
Err(_) => 0,
};
let orid = v.remove(0);
let tx_set = v.remove(0);
Dispute {
did: k,
created,
orid,
tx_set,
}
}
}

View file

@ -314,13 +314,14 @@ pub async fn verify(address: String, data: String, signature: String) -> String
}
/// Performs the xmr rpc 'create_wallet' method
pub async fn create_wallet(filename: String) -> bool {
pub async fn create_wallet(filename: String, password: &String) -> bool {
info!("executing {}", RpcFields::CreateWallet.value());
let client = reqwest::Client::new();
let host = get_rpc_host();
let params = reqres::XmrRpcCreateWalletParams {
filename,
language: String::from("English"),
password: String::from(password),
};
let req = reqres::XmrRpcCreateRequest {
jsonrpc: RpcFields::JsonRpcVersion.value(),
@ -354,11 +355,14 @@ pub async fn create_wallet(filename: String) -> bool {
}
/// Performs the xmr rpc 'open_wallet' method
pub async fn open_wallet(filename: String) -> bool {
pub async fn open_wallet(filename: String, password: &String) -> bool {
info!("executing {}", RpcFields::Open.value());
let client = reqwest::Client::new();
let host = get_rpc_host();
let params = reqres::XmrRpcOpenWalletParams { filename };
let params = reqres::XmrRpcOpenWalletParams {
filename,
password: String::from(password),
};
let req = reqres::XmrRpcOpenRequest {
jsonrpc: RpcFields::JsonRpcVersion.value(),
id: RpcFields::Id.value(),
@ -392,11 +396,14 @@ pub async fn open_wallet(filename: String) -> bool {
}
/// Performs the xmr rpc 'close_wallet' method
pub async fn close_wallet(filename: String) -> bool {
pub async fn close_wallet(filename: String, password: String) -> bool {
info!("executing {}", RpcFields::Close.value());
let client = reqwest::Client::new();
let host = get_rpc_host();
let params = reqres::XmrRpcOpenWalletParams { filename };
let params = reqres::XmrRpcOpenWalletParams {
filename,
password,
};
let req = reqres::XmrRpcOpenRequest {
jsonrpc: RpcFields::JsonRpcVersion.value(),
id: RpcFields::Id.value(),
@ -715,7 +722,7 @@ pub async fn sign_multisig(tx_data_hex: String) -> reqres::XmrRpcSignMultisigRes
}
}
/// Performs the xmr rpc 'sign_multisig' method
/// Performs the xmr rpc 'exchange_multisig_keys' method
pub async fn exchange_multisig_keys(
force_update_use_with_caution: bool,
multisig_info: String,

View file

@ -1,4 +1,4 @@
use crate::utils;
use crate::{utils, models};
use serde::{
Deserialize,
Serialize,
@ -29,11 +29,13 @@ pub struct XmrRpcVerifyParams {
pub struct XmrRpcCreateWalletParams {
pub filename: String,
pub language: String,
pub password: String,
}
#[derive(Deserialize, Serialize, Debug)]
pub struct XmrRpcOpenWalletParams {
pub filename: String,
pub password: String,
}
#[derive(Deserialize, Serialize, Debug)]
@ -875,8 +877,8 @@ impl Default for XmrRpcExchangeMultisigKeysResponse {
fn default() -> Self {
XmrRpcExchangeMultisigKeysResponse {
result: XmrRpcExchangeMultisigKeysResult {
address: Default::default(),
multisig_info: Default::default(),
address: utils::empty_string(),
multisig_info: utils::empty_string(),
},
}
}
@ -1078,3 +1080,307 @@ impl Default for ErrorResponse {
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetCustomerResponse {
pub address: String,
pub cid: String,
pub name: String,
pub pgp: String,
}
impl Default for GetCustomerResponse {
fn default() -> Self {
GetCustomerResponse {
address: utils::empty_string(),
cid: utils::empty_string(),
name: utils::empty_string(),
pgp: utils::empty_string(),
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetVendorResponse {
pub vid: String,
pub active: bool,
pub address: String,
pub description: String,
pub name: String,
pub pgp: String,
}
impl Default for GetVendorResponse {
fn default() -> Self {
GetVendorResponse {
vid: utils::empty_string(),
active: false,
address: utils::empty_string(),
description: utils::empty_string(),
name: utils::empty_string(),
pgp: utils::empty_string(),
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetProductResponse {
pub pid: String,
pub in_stock: bool,
pub description: String,
pub name: String,
pub price: i64,
pub qty: i64,
}
impl Default for GetProductResponse {
fn default() -> Self {
GetProductResponse {
pid: utils::empty_string(),
in_stock: false,
description: utils::empty_string(),
name: utils::empty_string(),
price: 0,
qty: 0,
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetVendorProductsResponse {
pub products: Vec<GetProductResponse>,
}
impl Default for GetVendorProductsResponse {
fn default() -> Self {
GetVendorProductsResponse {
products: Vec::new(),
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetAuthResponse {
pub address: String,
pub aid: String,
pub created: i64,
pub cvid: String,
pub data: String,
pub token: String,
}
impl Default for GetAuthResponse {
fn default() -> Self {
GetAuthResponse {
address: utils::empty_string(),
aid: utils::empty_string(),
created: 0,
cvid: utils::empty_string(),
data: utils::empty_string(),
token: utils::empty_string(),
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetDisputeResponse {
pub orid: String,
pub created: i64,
pub tx_set: String,
}
impl Default for GetDisputeResponse {
fn default() -> Self {
GetDisputeResponse {
orid: utils::empty_string(),
created: 0,
tx_set: utils::empty_string(),
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetOrderResponse {
pub orid: String,
pub pid: String,
pub xmr_address: String,
pub cust_msig_info: String,
pub cust_kex_1: String,
pub cust_kex_2: String,
pub cust_kex_3: String,
pub date: i64,
pub deliver_date: i64,
pub ship_date: i64,
pub hash: String,
pub msig_prepare: String,
pub msig_make: String,
pub msig_kex_1: String,
pub msig_kex_2: String,
pub msig_kex_3: String,
pub subaddress: String,
pub status: String,
pub quantity: i64,
pub vend_kex_1: String,
pub vend_kex_2: String,
pub vend_kex_3: String,
pub vend_msig_info: String,
}
impl Default for GetOrderResponse {
fn default() -> Self {
GetOrderResponse {
orid: utils::empty_string(),
pid: utils::empty_string(),
xmr_address: utils::empty_string(),
cust_msig_info: utils::empty_string(),
cust_kex_1: utils::empty_string(),
cust_kex_2: utils::empty_string(),
cust_kex_3: utils::empty_string(),
date: 0,
deliver_date: 0,
ship_date: 0,
hash: utils::empty_string(),
msig_prepare: utils::empty_string(),
msig_make: utils::empty_string(),
msig_kex_1: utils::empty_string(),
msig_kex_2: utils::empty_string(),
msig_kex_3: utils::empty_string(),
subaddress: utils::empty_string(),
status: utils::empty_string(),
quantity: 0,
vend_kex_1: utils::empty_string(),
vend_kex_2: utils::empty_string(),
vend_kex_3: utils::empty_string(),
vend_msig_info: utils::empty_string(),
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct GetOrdersResponse {
pub orders: Vec<GetOrderResponse>,
}
impl Default for GetOrdersResponse {
fn default() -> Self {
GetOrdersResponse {
orders: Vec::new(),
}
}
}
// START response builders
impl GetDisputeResponse {
pub fn build(m_dispute: models::Dispute) -> Self {
GetDisputeResponse {
orid: m_dispute.orid,
created: m_dispute.created,
tx_set: m_dispute.tx_set,
}
}
}
impl GetProductResponse {
pub fn build(m_product: models::Product) -> Self {
GetProductResponse {
pid: m_product.pid,
in_stock: m_product.in_stock,
description: m_product.description,
name: m_product.name,
price: m_product.price,
qty: m_product.qty,
}
}
}
impl GetVendorProductsResponse {
pub fn build(m_products: Vec<models::Product>) -> Self {
let mut v_res: Vec<GetProductResponse> = Vec::new();
for m in m_products {
let p_res: GetProductResponse = GetProductResponse {
pid: m.pid,
in_stock: m.in_stock,
description: m.description,
name: m.name,
price: m.price,
qty: m.qty,
};
v_res.push(p_res);
}
GetVendorProductsResponse { products: v_res }
}
}
impl GetOrderResponse {
pub fn build(pid: String, m_order: models::Order) -> Self {
GetOrderResponse {
orid: m_order.orid,
pid,
xmr_address: m_order.xmr_address,
cust_msig_info: m_order.cust_msig_info,
cust_kex_1: m_order.cust_kex_1,
cust_kex_2: m_order.cust_kex_2,
cust_kex_3: m_order.cust_kex_3,
date: m_order.date,
deliver_date: m_order.deliver_date,
ship_date: m_order.ship_date,
hash: m_order.hash,
msig_prepare: m_order.msig_prepare,
msig_make: m_order.msig_make,
msig_kex_1: m_order.msig_kex_1,
msig_kex_2: m_order.msig_kex_2,
msig_kex_3: m_order.msig_kex_3,
subaddress: m_order.subaddress,
status: m_order.status,
quantity: m_order.quantity,
vend_kex_1: m_order.vend_kex_1,
vend_kex_2: m_order.vend_kex_2,
vend_kex_3: m_order.vend_kex_3,
vend_msig_info: m_order.vend_msig_info,
}
}
}
impl GetOrdersResponse {
pub fn build(m_orders: Vec<models::Order>) -> Self {
let mut v_res: Vec<GetOrderResponse> = Vec::new();
for m in m_orders {
let o_res: GetOrderResponse = GetOrderResponse {
orid: m.orid,
pid: m.p_id,
xmr_address: m.xmr_address,
cust_msig_info: m.cust_msig_info,
cust_kex_1: m.cust_kex_1,
cust_kex_2: m.cust_kex_2,
cust_kex_3: m.cust_kex_3,
date: m.date,
deliver_date: m.deliver_date,
ship_date: m.ship_date,
hash: m.hash,
msig_prepare: m.msig_prepare,
msig_make: m.msig_make,
msig_kex_1: m.msig_kex_1,
msig_kex_2: m.msig_kex_2,
msig_kex_3: m.msig_kex_3,
subaddress: m.subaddress,
status: m.status,
quantity: m.quantity,
vend_kex_1: m.vend_kex_1,
vend_kex_2: m.vend_kex_2,
vend_kex_3: m.vend_kex_3,
vend_msig_info: m.vend_msig_info,
};
v_res.push(o_res);
}
GetOrdersResponse { orders: v_res }
}
}
// END response builders

View file

@ -270,16 +270,16 @@ fn create_wallet_dir() {
}
/// Generate application wallet at startup if none exist
async fn gen_app_wallet() {
async fn gen_app_wallet(password: &String) {
info!("fetching application wallet");
let filename = "nevmes";
let mut m_wallet = monero::open_wallet(String::from(filename)).await;
let mut m_wallet = monero::open_wallet(String::from(filename), password).await;
if !m_wallet {
m_wallet = monero::create_wallet(String::from(filename)).await;
m_wallet = monero::create_wallet(String::from(filename), password).await;
if !m_wallet {
error!("failed to create wallet")
} else {
m_wallet = monero::open_wallet(String::from(filename)).await;
m_wallet = monero::open_wallet(String::from(filename), password).await;
if m_wallet {
let m_address: reqres::XmrRpcAddressResponse = monero::get_address().await;
info!("app wallet address: {}", m_address.result.address)
@ -404,7 +404,9 @@ pub async fn start_up() {
// wait for rpc server for a bit
tokio::time::sleep(std::time::Duration::new(5, 0)).await;
monero::check_rpc_connection().await;
gen_app_wallet().await;
let wallet_password = std::env::var(crate::MONERO_WALLET_PASSWORD)
.unwrap_or(String::from("password"));
gen_app_wallet(&wallet_password).await;
i2p::start().await;
gen_app_gpg().await;
let env: String = get_release_env().value();