use std::sync::Mutex; use base64::engine::general_purpose::STANDARD; use base64::Engine; use hyper::StatusCode; use rsa::RsaPrivateKey; use rusqlite::Connection; use rust_util::{opt_result, simple_error, XResult}; use seckey::SecBytes; use serde::{Deserialize, Serialize}; use serde_json::{json, Map, Value}; use crate::db; pub type GenericError = Box; pub type Result = std::result::Result; #[macro_export] macro_rules! do_response { ($ex: expr) => ( match $ex { Ok((status_code, body)) => Ok(Response::builder().status(status_code).body((serde_json::to_string_pretty(&body)? + "\n").into())?), Err(e) => Ok(Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body( format!("{}\n", serde_json::to_string_pretty(&json!({ "error": "internal_error", "error_message": format!("{}", e), }))?).into() )?), } ) } pub fn ok(body: Value) -> XResult<(StatusCode, Value)> { Ok((StatusCode::OK, body)) } pub fn client_error(error: &str) -> XResult<(StatusCode, Value)> { Ok(( StatusCode::BAD_REQUEST, json!({ "error": error }) )) } pub fn server_error(error: &str) -> XResult<(StatusCode, Value)> { Ok(( StatusCode::INTERNAL_SERVER_ERROR, json!({ "error": error }) )) } // pub fn bad_request(error: &str, error_message: &str) -> XResult<(StatusCode, Value)> { // Ok(( // StatusCode::BAD_REQUEST, // json!({ "error": error, "error_message": error_message }) // )) // } pub struct MemoryKey { pub database_file: String, pub instance_rsa_key_pair: RsaPrivateKey, pub master_key: Option, } lazy_static::lazy_static! { pub static ref STATUP_RW_LOCK: Mutex> = Mutex::new(None); } #[derive(Serialize, Deserialize)] pub struct MultipleViewValue { pub value: Option, pub value_hex: Option, pub value_base64: Option, } impl MultipleViewValue { pub fn from(v: &[u8]) -> Self { Self { value: Some(String::from_utf8_lossy(v).to_string()), value_hex: Some(hex::encode(v)), value_base64: Some(STANDARD.encode(v)), } } pub fn from_without_value(v: &[u8]) -> Self { Self { value: None, value_hex: Some(hex::encode(v)), value_base64: Some(STANDARD.encode(v)), } } pub fn to_bytes(&self) -> XResult> { if let Some(v) = &self.value { Ok(v.as_bytes().to_vec()) } else if let Some(v) = &self.value_hex { let v = opt_result!(hex::decode(v), "Decode hex failed: {}"); Ok(v) } else if let Some(v) = &self.value_base64 { let v = opt_result!(STANDARD.decode(v), "Decode base64 failed: {}"); Ok(v) } else { simple_error!("Multiple view value is all empty") } } } #[macro_export] macro_rules! require_master_key { () => { match $crate::serve_common::get_master_key() { None => return $crate::serve_common::client_error("status_not_ready"), Some(key) => key, } }; } pub fn get_master_key() -> Option { let startup_rw_lock = STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error"); match &*startup_rw_lock { None => None, Some(k) => match &k.master_key { None => None, Some(k) => { let k = &*k.read(); Some(SecBytes::with(k.len(), |buf| buf.copy_from_slice(k))) } }, } } pub fn byte_to_multi_view_map(bytes: &[u8], with_value: bool) -> Map { let v = if with_value { MultipleViewValue::from(bytes) } else { MultipleViewValue::from_without_value(bytes) }; let mut map = Map::new(); if let Some(v) = &v.value { map.insert("value".to_string(), Value::String(v.to_string())); } if let Some(v) = &v.value_hex { map.insert("value_hex".to_string(), Value::String(v.to_string())); } if let Some(v) = &v.value_base64 { map.insert("value_base64".to_string(), Value::String(v.to_string())); } map } pub fn open_local_db() -> XResult { let startup_rw_lock = STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error"); match &*startup_rw_lock { None => simple_error!("Db is not initiated!"), Some(k) => { Ok(opt_result!(db::open_db(& k.database_file), "Open db failed: {}")) } } }