158 lines
4.6 KiB
Rust
158 lines
4.6 KiB
Rust
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<dyn std::error::Error + Send + Sync>;
|
|
pub type Result<T> = std::result::Result<T, GenericError>;
|
|
|
|
#[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<SecBytes>,
|
|
}
|
|
|
|
lazy_static::lazy_static! {
|
|
pub static ref STATUP_RW_LOCK: Mutex<Option<MemoryKey>> = Mutex::new(None);
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct MultipleViewValue {
|
|
pub value: Option<String>,
|
|
pub value_hex: Option<String>,
|
|
pub value_base64: Option<String>,
|
|
}
|
|
|
|
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<Vec<u8>> {
|
|
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<SecBytes> {
|
|
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<String, Value> {
|
|
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<Connection> {
|
|
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: {}"))
|
|
}
|
|
}
|
|
}
|