103 lines
3.1 KiB
Rust
103 lines
3.1 KiB
Rust
use hyper::{Body, Request, Response, StatusCode};
|
|
use hyper::body::Buf;
|
|
use rust_util::{simple_error, XResult};
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::{json, Value};
|
|
|
|
use crate::{db, jose};
|
|
use crate::db::Key;
|
|
use crate::do_response;
|
|
use crate::serve_common::{byte_to_multi_view_map, get_master_key, MultipleViewValue, open_local_db};
|
|
use crate::serve_common::Result;
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
struct Named {
|
|
name: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
struct NamedValue {
|
|
name: String,
|
|
force_write: Option<bool>,
|
|
value: MultipleViewValue,
|
|
}
|
|
|
|
pub async fn read(req: Request<Body>) -> Result<Response<Body>> {
|
|
do_response!(inner_read(req).await)
|
|
}
|
|
|
|
async fn inner_read(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|
let whole_body = hyper::body::aggregate(req).await?;
|
|
let named: Named = serde_json::from_reader(whole_body.reader())?;
|
|
let name = &named.name;
|
|
if name.is_empty() {
|
|
return simple_error!("Key name cannot be empty");
|
|
}
|
|
let db_key_name = db::make_db_key_name(name);
|
|
|
|
let conn = open_local_db()?;
|
|
let db_key = db::find_key(&conn, &db_key_name)?;
|
|
|
|
let db_key_value = match db_key {
|
|
None => return simple_error!("Key '{}' already exists", name),
|
|
Some(k) => k,
|
|
};
|
|
|
|
let key = match get_master_key() {
|
|
None => return Ok((StatusCode::BAD_REQUEST, json!({ "error": "status_not_ready" }))),
|
|
Some(key) => key,
|
|
};
|
|
let data = jose::deserialize_jwe_aes(&db_key_value.encrypted_key, &*key.read())?;
|
|
drop(key);
|
|
|
|
let mut map = byte_to_multi_view_map(&data.0);
|
|
map.insert("name".to_string(), Value::String(name.to_string()));
|
|
Ok((StatusCode::OK, Value::Object(map)))
|
|
}
|
|
|
|
pub async fn write(req: Request<Body>) -> Result<Response<Body>> {
|
|
do_response!(inner_write(req).await)
|
|
}
|
|
|
|
async fn inner_write(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|
let whole_body = hyper::body::aggregate(req).await?;
|
|
let named_value: NamedValue = serde_json::from_reader(whole_body.reader())?;
|
|
let name = &named_value.name;
|
|
if name.is_empty() {
|
|
return simple_error!("Key name cannot be empty");
|
|
}
|
|
let db_key_name = db::make_db_key_name(name);
|
|
let force_write = named_value.force_write.unwrap_or(false);
|
|
|
|
let conn = open_local_db()?;
|
|
let db_key = db::find_key(&conn, &db_key_name)?;
|
|
|
|
if db_key.is_some() && !force_write {
|
|
return simple_error!("Key '{}' already exists", name);
|
|
}
|
|
|
|
let value = named_value.value.to_bytes()?;
|
|
let key = match get_master_key() {
|
|
None => return Ok((StatusCode::BAD_REQUEST, json!({ "error": "status_not_ready" }))),
|
|
Some(key) => key,
|
|
};
|
|
let encrypt_value = jose::serialize_jwe_aes(&value, &*key.read())?;
|
|
drop(key);
|
|
|
|
let new_db_key = Key {
|
|
name: db_key_name,
|
|
encrypted_key: encrypt_value.clone(),
|
|
};
|
|
if db_key.is_some() {
|
|
db::update_key(&conn, &new_db_key)?;
|
|
} else {
|
|
db::insert_key(&conn, &new_db_key)?;
|
|
}
|
|
|
|
Ok((StatusCode::OK, json!({
|
|
"name": name.to_string(),
|
|
"override": db_key.is_some(),
|
|
"encrypted_value": encrypt_value,
|
|
})))
|
|
}
|