Jf/register cache (#52)

Co-authored-by: operarotas <james.foley@proton.me>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Will Galebach 2023-11-13 14:58:15 +00:00 committed by GitHub
parent 0ddb90a17a
commit 987a160daf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 16 deletions

View File

@ -112,6 +112,14 @@ pub fn decode_keyfile(keyfile: Vec<u8>, password: &str) -> Result<Keyfile, &'sta
}) })
} }
pub fn get_username(keyfile: Vec<u8>) -> Result<String, &'static str> {
let (username, _routers, _salt, _key_enc, _jwt_enc, _file_enc) =
bincode::deserialize::<(String, Vec<String>, Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>)>(&keyfile)
.map_err(|_| "failed to deserialize keyfile")?;
Ok(username)
}
/// # Returns /// # Returns
/// a pair of (public key (encoded as a hex string), serialized key as a pkcs8 Document) /// a pair of (public key (encoded as a hex string), serialized key as a pkcs8 Document)
pub fn generate_networking_key() -> (String, Document) { pub fn generate_networking_key() -> (String, Document) {

View File

@ -186,6 +186,7 @@ async fn main() {
// if any do not match, we should prompt user to create a "transaction" // if any do not match, we should prompt user to create a "transaction"
// that updates their PKI info on-chain. // that updates their PKI info on-chain.
let http_server_port = http_server::find_open_port(8080).await.unwrap(); let http_server_port = http_server::find_open_port(8080).await.unwrap();
println!("Login or Register at http://localhost:{}", http_server_port);
let (kill_tx, kill_rx) = oneshot::channel::<bool>(); let (kill_tx, kill_rx) = oneshot::channel::<bool>();
let disk_keyfile = match fs::read(format!("{}/.keys", home_directory_path)).await { let disk_keyfile = match fs::read(format!("{}/.keys", home_directory_path)).await {

@ -1 +1 @@
Subproject commit 81654a0ed724a62748e49feb0c97fad50f1e243a Subproject commit 7120168626f4e9b09008844174c63fc30af8711f

View File

@ -11,7 +11,7 @@ use std::sync::{Arc, Mutex};
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use warp::{ use warp::{
http::{ http::{
header::{HeaderValue, SET_COOKIE}, header::{HeaderMap, HeaderValue, SET_COOKIE},
StatusCode, StatusCode,
}, },
Filter, Rejection, Reply, Filter, Rejection, Reply,
@ -59,10 +59,13 @@ pub async fn register(
let keyfile_vet = keyfile_arc.clone(); let keyfile_vet = keyfile_arc.clone();
let static_files = warp::path("static").and(warp::fs::dir("./src/register/build/static/")); let static_files = warp::path("static").and(warp::fs::dir("./src/register/build/static/"));
let react_app = warp::path::end() let react_app = warp::path::end()
.and(warp::get()) .and(warp::get())
.and(warp::fs::file("./src/register/build/index.html")); .and(warp::fs::file("./src/register/build/index.html"));
let keyfile_vet_copy = keyfile_vet.clone();
let api = warp::path("has-keyfile") let api = warp::path("has-keyfile")
.and( .and(
warp::get() warp::get()
@ -74,6 +77,7 @@ pub async fn register(
.and(warp::any().map(move || ip.clone())) .and(warp::any().map(move || ip.clone()))
.and(warp::any().map(move || our_ws_info.clone())) .and(warp::any().map(move || our_ws_info.clone()))
.and(warp::any().map(move || net_keypair_ws_info.clone())) .and(warp::any().map(move || net_keypair_ws_info.clone()))
.and(warp::any().map(move || keyfile_vet_copy.clone()))
.and_then(handle_info), .and_then(handle_info),
)) ))
.or(warp::path("vet-keyfile").and( .or(warp::path("vet-keyfile").and(
@ -94,7 +98,16 @@ pub async fn register(
.and_then(handle_boot), .and_then(handle_boot),
)); ));
let routes = static_files.or(react_app).or(api); let mut headers = HeaderMap::new();
headers.insert(
"Cache-Control",
HeaderValue::from_static("no-store, no-cache, must-revalidate, proxy-revalidate"),
);
let routes = static_files
.or(react_app)
.or(api)
.with(warp::reply::with::headers(headers));
let _ = open::that(format!("http://localhost:{}/", port)); let _ = open::that(format!("http://localhost:{}/", port));
warp::serve(routes) warp::serve(routes)
@ -115,10 +128,13 @@ async fn handle_has_keyfile(keyfile: Arc<Mutex<Option<Vec<u8>>>>) -> Result<impl
let encoded_keyfile = keyfile_lock.as_ref().unwrap(); let encoded_keyfile = keyfile_lock.as_ref().unwrap();
let username: String = match encoded_keyfile.is_empty() { let username: String = match encoded_keyfile.is_empty() {
true => "".to_string(), true => "".to_string(),
false => { false => match bincode::deserialize(encoded_keyfile) {
let (user, ..): (String,) = bincode::deserialize(encoded_keyfile).unwrap(); Ok(k) => {
let (user, ..): (String,) = k;
user user
} }
Err(_) => "".to_string(),
},
}; };
Ok(warp::reply::json(&username)) Ok(warp::reply::json(&username))
@ -155,9 +171,11 @@ async fn handle_boot(
sender: RegistrationSender, sender: RegistrationSender,
mut our: Identity, mut our: Identity,
networking_keypair: Document, networking_keypair: Document,
mut encoded_keyfile: Vec<u8>, encoded_keyfile: Vec<u8>,
) -> Result<impl Reply, Rejection> { ) -> Result<impl Reply, Rejection> {
if !info.username.is_empty() {
our.name = info.username; our.name = info.username;
}
if info.direct { if info.direct {
our.allowed_routers = vec![]; our.allowed_routers = vec![];
@ -166,12 +184,20 @@ async fn handle_boot(
} }
// if keyfile was not present in node and is present from user upload // if keyfile was not present in node and is present from user upload
if encoded_keyfile.is_empty() && !info.keyfile.clone().is_empty() { let mut encoded_keyfile = if !info.keyfile.clone().is_empty() {
match base64::decode(info.keyfile.clone()) { match base64::decode(info.keyfile.clone()) {
Ok(k) => encoded_keyfile = k, Ok(k) => k,
Err(_) => return Err(warp::reject()), Err(_) => {
return Ok(warp::reply::with_status(
warp::reply::json(&"Keyfile not valid base64".to_string()),
StatusCode::BAD_REQUEST,
)
.into_response())
} }
} }
} else {
encoded_keyfile
};
// if keyfile was not in node or upload or if networking required reset // if keyfile was not in node or upload or if networking required reset
let decoded_keyfile = if info.reset || encoded_keyfile.is_empty() { let decoded_keyfile = if info.reset || encoded_keyfile.is_empty() {
@ -190,13 +216,20 @@ async fn handle_boot(
} else { } else {
match keygen::decode_keyfile(encoded_keyfile.clone(), &info.password) { match keygen::decode_keyfile(encoded_keyfile.clone(), &info.password) {
Ok(k) => { Ok(k) => {
our.name = k.username.clone();
our.networking_key = format!( our.networking_key = format!(
"0x{}", "0x{}",
hex::encode(k.networking_keypair.public_key().as_ref()) hex::encode(k.networking_keypair.public_key().as_ref())
); );
k k
} }
Err(_) => return Err(warp::reject()), Err(_) => {
return Ok(warp::reply::with_status(
warp::reply::json(&"Failed to decode keyfile".to_string()),
StatusCode::INTERNAL_SERVER_ERROR,
)
.into_response())
}
} }
}; };
@ -213,7 +246,13 @@ async fn handle_boot(
let token = match generate_jwt(&decoded_keyfile.jwt_secret_bytes, our.name.clone()) { let token = match generate_jwt(&decoded_keyfile.jwt_secret_bytes, our.name.clone()) {
Some(token) => token, Some(token) => token,
None => return Err(warp::reject()), None => {
return Ok(warp::reply::with_status(
warp::reply::json(&"Failed to generate JWT".to_string()),
StatusCode::SERVICE_UNAVAILABLE,
)
.into_response())
}
}; };
sender sender
@ -247,11 +286,22 @@ async fn handle_info(
ip: String, ip: String,
our_arc: Arc<Mutex<Option<Identity>>>, our_arc: Arc<Mutex<Option<Identity>>>,
networking_keypair_arc: Arc<Mutex<Option<Document>>>, networking_keypair_arc: Arc<Mutex<Option<Document>>>,
keyfile_arc: Arc<Mutex<Option<Vec<u8>>>>,
) -> Result<impl Reply, Rejection> { ) -> Result<impl Reply, Rejection> {
// 1. Generate networking keys // 1. Generate networking keys
let (public_key, serialized_networking_keypair) = keygen::generate_networking_key(); let (public_key, serialized_networking_keypair) = keygen::generate_networking_key();
*networking_keypair_arc.lock().unwrap() = Some(serialized_networking_keypair); *networking_keypair_arc.lock().unwrap() = Some(serialized_networking_keypair);
let username = {
match keyfile_arc.lock().unwrap().clone() {
None => String::new(),
Some(encoded_keyfile) => match keygen::get_username(encoded_keyfile) {
Ok(k) => k,
Err(_) => String::new(),
},
}
};
// 2. set our... // 2. set our...
// TODO: if IP is localhost, assign a router... // TODO: if IP is localhost, assign a router...
let ws_port = http_server::find_open_port(9000).await.unwrap(); let ws_port = http_server::find_open_port(9000).await.unwrap();
@ -260,7 +310,7 @@ async fn handle_info(
// to match on // to match on
let our = Identity { let our = Identity {
networking_key: format!("0x{}", public_key), networking_key: format!("0x{}", public_key),
name: String::new(), name: username,
ws_routing: Some((ip.clone(), ws_port)), ws_routing: Some((ip.clone(), ws_port)),
allowed_routers: vec![ allowed_routers: vec![
"uqbar-router-1.uq".into(), // "0x8d9e54427c50660c6d4802f63edca86a9ca5fd6a78070c4635950e9d149ed441".into(), "uqbar-router-1.uq".into(), // "0x8d9e54427c50660c6d4802f63edca86a9ca5fd6a78070c4635950e9d149ed441".into(),