From 7413646fc47e0e07043dfc17f4a73a081cd6bec9 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Mon, 8 Jul 2024 16:56:14 -0700 Subject: [PATCH 01/14] fix caps by hashing JSON-ified params (to avoid, eg, whitespace diffs) --- lib/src/core.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/src/core.rs b/lib/src/core.rs index 35316e22c..90fbe7152 100644 --- a/lib/src/core.rs +++ b/lib/src/core.rs @@ -3,6 +3,7 @@ use ring::signature; use rusqlite::types::{FromSql, FromSqlError, ToSql, ValueRef}; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap, HashSet}; +use std::hash::{Hash, Hasher}; use thiserror::Error; lazy_static::lazy_static! { @@ -470,7 +471,7 @@ pub enum Message { Response((Response, Option)), } -#[derive(Clone, Debug, Hash, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Capability { pub issuer: Address, pub params: String, @@ -488,6 +489,15 @@ impl PartialEq for Capability { } } +impl Hash for Capability { + fn hash(&self, state: &mut H) { + self.issuer.hash(state); + let params: serde_json::Value = + serde_json::from_str(&self.params).unwrap_or_default(); + params.hash(state); + } +} + impl Capability { pub fn new(issuer: T, params: U) -> Self where From 1cd887398d31627f11ddc667df9db125baab4765 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:56:39 +0000 Subject: [PATCH 02/14] Format Rust code using rustfmt --- lib/src/core.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/core.rs b/lib/src/core.rs index 90fbe7152..2e4607002 100644 --- a/lib/src/core.rs +++ b/lib/src/core.rs @@ -492,8 +492,7 @@ impl PartialEq for Capability { impl Hash for Capability { fn hash(&self, state: &mut H) { self.issuer.hash(state); - let params: serde_json::Value = - serde_json::from_str(&self.params).unwrap_or_default(); + let params: serde_json::Value = serde_json::from_str(&self.params).unwrap_or_default(); params.hash(state); } } From 70de31a97a91fef465a03f0368da05a8b053a0f5 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Mon, 8 Jul 2024 17:00:51 -0700 Subject: [PATCH 03/14] bump version to 0.8.3 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74b35d70f..358103fed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3212,7 +3212,7 @@ dependencies = [ [[package]] name = "kinode" -version = "0.8.2" +version = "0.8.3" dependencies = [ "aes-gcm", "alloy", diff --git a/Cargo.toml b/Cargo.toml index 260f70421..15c40cb9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kinode_lib" authors = ["KinodeDAO"] -version = "0.8.2" +version = "0.8.3" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" From c4d0e07ba0c67c0230d0ff49cf1a77e723fe4612 Mon Sep 17 00:00:00 2001 From: doria <93405247+dr-frmr@users.noreply.github.com> Date: Wed, 10 Jul 2024 08:54:01 +0900 Subject: [PATCH 04/14] Update Cargo.toml --- lib/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 80fa82f8d..9d8147d06 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lib" authors = ["KinodeDAO"] -version = "0.8.2" +version = "0.8.3" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" From bde0f43374f4682901a68914e5214deb1c724464 Mon Sep 17 00:00:00 2001 From: doria <93405247+dr-frmr@users.noreply.github.com> Date: Wed, 10 Jul 2024 08:54:25 +0900 Subject: [PATCH 05/14] Update Cargo.toml 2 --- kinode/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kinode/Cargo.toml b/kinode/Cargo.toml index 7ea062d09..3158632fb 100644 --- a/kinode/Cargo.toml +++ b/kinode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kinode" authors = ["KinodeDAO"] -version = "0.8.2" +version = "0.8.3" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" From 89213a92fe47ecf6810746c37b3963009606241f Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Wed, 10 Jul 2024 17:27:49 -0700 Subject: [PATCH 06/14] fix login redirects for all but login+secure+query params --- Cargo.lock | 4 +-- kinode/packages/settings/settings/src/lib.rs | 9 ++++--- kinode/src/http/login.html | 27 ++++++++++++++++---- kinode/src/http/server.rs | 26 +++---------------- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 358103fed..43e57ca39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3269,7 +3269,7 @@ dependencies = [ [[package]] name = "kinode_lib" -version = "0.8.2" +version = "0.8.3" dependencies = [ "lib", ] @@ -3391,7 +3391,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "lib" -version = "0.8.2" +version = "0.8.3" dependencies = [ "alloy", "kit", diff --git a/kinode/packages/settings/settings/src/lib.rs b/kinode/packages/settings/settings/src/lib.rs index e461bd58e..ec606c8fd 100644 --- a/kinode/packages/settings/settings/src/lib.rs +++ b/kinode/packages/settings/settings/src/lib.rs @@ -157,9 +157,12 @@ fn initialize(our: Address) { .unwrap(); // Serve the index.html and other UI files found in pkg/ui at the root path. - http::serve_ui(&our, "ui", true, false, vec!["/"]).unwrap(); - http::bind_http_path("/ask", true, false).unwrap(); - http::bind_ws_path("/", true, false).unwrap(); + //http::serve_ui(&our, "ui", true, false, vec!["/"]).unwrap(); + //http::bind_http_path("/ask", true, false).unwrap(); + //http::bind_ws_path("/", true, false).unwrap(); + http::secure_serve_ui(&our, "ui", vec!["/"]).unwrap(); + http::secure_bind_http_path("/ask").unwrap(); + http::secure_bind_ws_path("/", false).unwrap(); // Grab our state, then enter the main event loop. let mut state: SettingsState = SettingsState::new(our); diff --git a/kinode/src/http/login.html b/kinode/src/http/login.html index aedca7169..1709a2d93 100644 --- a/kinode/src/http/login.html +++ b/kinode/src/http/login.html @@ -1194,10 +1194,13 @@

Logging in...

} const firstPathItem = window.location.pathname.split('/')[1]; - if (firstPathItem === '') { - document.getElementById("node-and-domain").innerText = "${node} "; - } else { + const expectedSecureSubdomain = generateSecureSubdomain(firstPathItem); + const maybeSecureSubdomain = window.location.host.split('.')[0]; + const isSecureSubdomain = expectedSecureSubdomain === maybeSecureSubdomain; + if (isSecureSubdomain) { document.getElementById("node-and-domain").innerText = "${node}: authenticate for secure subdomain app " + firstPathItem; + } else { + document.getElementById("node-and-domain").innerText = "${node} "; } async function login(password) { @@ -1210,7 +1213,10 @@

Logging in...

const result = await fetch("/login", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ password_hash: hashHex, subdomain: firstPathItem }), + body: JSON.stringify({ + password_hash: hashHex, + subdomain: isSecureSubdomain ? firstPathItem : '', + }), }); if (result.status == 200) { @@ -1226,6 +1232,17 @@

Logging in...

} } + function generateSecureSubdomain(processString) { + const parts = processString.split(':'); + const package = parts[1]; + const publisher = parts[2]; + const subdomain = [package, publisher].join("-") + .split("") + .map(c => c.match(/[a-zA-Z0-9]/) ? c : '-') + .join(""); + return subdomain; + } + document.addEventListener("DOMContentLoaded", () => { const form = document.getElementById("signup-form"); form.addEventListener("submit", (e) => { @@ -1238,4 +1255,4 @@

Logging in...

- \ No newline at end of file + diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index 0ff828062..8e515ef37 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -584,28 +584,10 @@ async fn http_handler( &jwt_secret_bytes, ) { // redirect to login page so they can get an auth token - if original_path == "" { - return Ok(warp::http::Response::builder() - .status(StatusCode::OK) - .body(login_html.to_string()) - .into_response()); - } else { - return Ok(warp::http::Response::builder() - .status(StatusCode::TEMPORARY_REDIRECT) - .header( - "Location", - format!( - "{}://{}", - match headers.get("X-Forwarded-Proto") { - Some(proto) => proto.to_str().unwrap_or("http"), - None => "http", - }, - host, - ), - ) - .body(vec![]) - .into_response()); - } + return Ok(warp::http::Response::builder() + .status(StatusCode::OK) + .body(login_html.to_string()) + .into_response()); } } } From b4395e074b8d778da6d7db46f99dab7cd1f468af Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Wed, 10 Jul 2024 17:30:23 -0700 Subject: [PATCH 07/14] fix login+secure+query params case; h/t bacwyls source: https://github.com/bacwyls/kinode/commit/396a9015a4eb351298558bfbff7b69a8dda5f74e --- kinode/src/http/server.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index 8e515ef37..b660d576a 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -546,12 +546,21 @@ async fn http_handler( .into_response()); } if request_subdomain != subdomain { + let query_string = if !query_params.is_empty() { + let params: Vec = query_params.iter() + .map(|(key, value)| format!("{}={}", key, value)) + .collect(); + format!("?{}", params.join("&")) + } else { + String::new() + }; + return Ok(warp::http::Response::builder() .status(StatusCode::TEMPORARY_REDIRECT) .header( "Location", format!( - "{}://{}.{}{}", + "{}://{}.{}{}{}", match headers.get("X-Forwarded-Proto") { Some(proto) => proto.to_str().unwrap_or("http"), None => "http", @@ -559,6 +568,7 @@ async fn http_handler( subdomain, host, original_path, + query_string, ), ) .body(vec![]) From dc933503b14030f587f34af0571eefcfabdce1d1 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Wed, 10 Jul 2024 17:32:08 -0700 Subject: [PATCH 08/14] make settings non-secure again --- kinode/packages/settings/settings/src/lib.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/kinode/packages/settings/settings/src/lib.rs b/kinode/packages/settings/settings/src/lib.rs index ec606c8fd..e461bd58e 100644 --- a/kinode/packages/settings/settings/src/lib.rs +++ b/kinode/packages/settings/settings/src/lib.rs @@ -157,12 +157,9 @@ fn initialize(our: Address) { .unwrap(); // Serve the index.html and other UI files found in pkg/ui at the root path. - //http::serve_ui(&our, "ui", true, false, vec!["/"]).unwrap(); - //http::bind_http_path("/ask", true, false).unwrap(); - //http::bind_ws_path("/", true, false).unwrap(); - http::secure_serve_ui(&our, "ui", vec!["/"]).unwrap(); - http::secure_bind_http_path("/ask").unwrap(); - http::secure_bind_ws_path("/", false).unwrap(); + http::serve_ui(&our, "ui", true, false, vec!["/"]).unwrap(); + http::bind_http_path("/ask", true, false).unwrap(); + http::bind_ws_path("/", true, false).unwrap(); // Grab our state, then enter the main event loop. let mut state: SettingsState = SettingsState::new(our); From 5dab722d779f3a5afa1db5b394b0b1aec53c53ee Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 00:32:34 +0000 Subject: [PATCH 09/14] Format Rust code using rustfmt --- kinode/src/http/server.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index b660d576a..004fbfc08 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -547,7 +547,8 @@ async fn http_handler( } if request_subdomain != subdomain { let query_string = if !query_params.is_empty() { - let params: Vec = query_params.iter() + let params: Vec = query_params + .iter() .map(|(key, value)| format!("{}={}", key, value)) .collect(); format!("?{}", params.join("&")) From 82ae77c9abbd01256fbc5e905fa7e15a3b02d217 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Wed, 10 Jul 2024 20:26:26 -0700 Subject: [PATCH 10/14] add valet button to login for hosted nodes --- kinode/src/http/login.html | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/kinode/src/http/login.html b/kinode/src/http/login.html index 1709a2d93..dce382e63 100644 --- a/kinode/src/http/login.html +++ b/kinode/src/http/login.html @@ -1138,6 +1138,35 @@ --tw-grayscale: grayscale(100%); filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } + + .top-left-button { + position: absolute; + top: 2rem; + left: 2rem; + width: 3rem; + height: 3rem; + border-radius: 50%; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.3s; + border: 1px solid white; + } + + .top-left-button img { + width: 2.5rem; + height: 2.5rem; + border-radius: 50%; + } + + .top-left-button:hover { + background-color: black; + } + + .hidden { + display: none; + } @@ -1145,6 +1174,11 @@ style="background-color: #22211f; background-image: linear-gradient(-55deg, #f75a2977 0%, transparent 72.05%),linear-gradient(-11deg, #86000172 3%, transparent 57.05%);"> +
Logging in... document.getElementById("fake-or-not").innerHTML = "To change your networking info, please restart your node."; } + if (isHosted(window.location.host)) { + document.getElementById("valet-button").classList.remove("hidden"); + } + const firstPathItem = window.location.pathname.split('/')[1]; const expectedSecureSubdomain = generateSecureSubdomain(firstPathItem); const maybeSecureSubdomain = window.location.host.split('.')[0]; @@ -1243,6 +1281,18 @@

Logging in...

return subdomain; } + function isHosted(host) { + const parts = host.split('.'); + if (parts.length < 3) { + return false; + } + const [thirdLast, secondLast, last] = parts.slice(-3); + if (thirdLast === 'hosting' && secondLast === 'kinode' && last === 'net') { + return true; + } + return false; + } + document.addEventListener("DOMContentLoaded", () => { const form = document.getElementById("signup-form"); form.addEventListener("submit", (e) => { From 4c4654c89d6c6add002a6a94ddc3da7898465a22 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 15 Jul 2024 02:39:48 +0200 Subject: [PATCH 11/14] prints --- kinode/src/main.rs | 2 ++ kinode/src/register.rs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/kinode/src/main.rs b/kinode/src/main.rs index c4a1b0e81..bacd09cd4 100644 --- a/kinode/src/main.rs +++ b/kinode/src/main.rs @@ -224,6 +224,8 @@ async fn main() { } }; + println!("our: {:?}\r", our); + // the boolean flag determines whether the runtime module is *public* or not, // where public means that any process can always message it. #[allow(unused_mut)] diff --git a/kinode/src/register.rs b/kinode/src/register.rs index 21cb42b02..12964bf04 100644 --- a/kinode/src/register.rs +++ b/kinode/src/register.rs @@ -757,6 +757,11 @@ pub async fn assign_routing( ip & 0xFF ); + println!("routers: {:?}\r", routers); + println!("node_ip: {:?}\r", node_ip); + println!("ws: {:?}\r", ws); + println!("tcp: {:?}\r", tcp); + if !routers.is_empty() { // indirect node return Ok(()); From 2f93467bc9e923dd395f4813d3bb1c6a667c1bd4 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 15 Jul 2024 03:04:35 +0200 Subject: [PATCH 12/14] attempt to fix --- kinode/src/main.rs | 2 -- kinode/src/register.rs | 20 +------------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/kinode/src/main.rs b/kinode/src/main.rs index bacd09cd4..c4a1b0e81 100644 --- a/kinode/src/main.rs +++ b/kinode/src/main.rs @@ -224,8 +224,6 @@ async fn main() { } }; - println!("our: {:?}\r", our); - // the boolean flag determines whether the runtime module is *public* or not, // where public means that any process can always message it. #[allow(unused_mut)] diff --git a/kinode/src/register.rs b/kinode/src/register.rs index 12964bf04..954c99c71 100644 --- a/kinode/src/register.rs +++ b/kinode/src/register.rs @@ -707,7 +707,6 @@ pub async fn assign_routing( let namehash = FixedBytes::<32>::from_slice(&keygen::namehash(&our.name)); let ip_call = ipCall { _0: namehash }.abi_encode(); let key_call = keyCall { _0: namehash }.abi_encode(); - let router_call = routersCall { _0: namehash }.abi_encode(); let tx_input = TransactionInput::new(Bytes::from(ip_call)); let tx = TransactionRequest::default() .to(kns_address) @@ -737,18 +736,6 @@ pub async fn assign_routing( )); } - let router_tx_input = TransactionInput::new(Bytes::from(router_call)); - let router_tx = TransactionRequest::default() - .to(kns_address) - .input(router_tx_input); - - let Ok(routers) = provider.call(&router_tx).await else { - return Err(anyhow::anyhow!("Failed to fetch node routers from PKI")); - }; - let Ok(routers) = >>::abi_decode(&routers, false) else { - return Err(anyhow::anyhow!("Failed to decode node routers from PKI")); - }; - let node_ip = format!( "{}.{}.{}.{}", (ip >> 24) & 0xFF, @@ -757,12 +744,7 @@ pub async fn assign_routing( ip & 0xFF ); - println!("routers: {:?}\r", routers); - println!("node_ip: {:?}\r", node_ip); - println!("ws: {:?}\r", ws); - println!("tcp: {:?}\r", tcp); - - if !routers.is_empty() { + if !our.is_direct() { // indirect node return Ok(()); } From 6bac6b544be4c32086ae38e8c4a32433ba558bac Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 15 Jul 2024 03:16:03 +0200 Subject: [PATCH 13/14] fixed, also, ignore SIGPIPE --- kinode/src/terminal/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kinode/src/terminal/mod.rs b/kinode/src/terminal/mod.rs index 8b8326e90..02c080e1b 100644 --- a/kinode/src/terminal/mod.rs +++ b/kinode/src/terminal/mod.rs @@ -587,7 +587,7 @@ pub async fn terminal( _ = sigalrm.recv() => return Err(anyhow::anyhow!("exiting due to SIGALRM")), _ = sighup.recv() => return Err(anyhow::anyhow!("exiting due to SIGHUP")), _ = sigint.recv() => return Err(anyhow::anyhow!("exiting due to SIGINT")), - _ = sigpipe.recv() => return Err(anyhow::anyhow!("exiting due to SIGPIPE")), + _ = sigpipe.recv() => continue, // IGNORE SIGPIPE! _ = sigquit.recv() => return Err(anyhow::anyhow!("exiting due to SIGQUIT")), _ = sigterm.recv() => return Err(anyhow::anyhow!("exiting due to SIGTERM")), _ = sigusr1.recv() => return Err(anyhow::anyhow!("exiting due to SIGUSR1")), From 9f2e3e1cab2d0d6379469667b13f3999774b2ea4 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 15 Jul 2024 12:55:13 +0200 Subject: [PATCH 14/14] fix delete key --- .../packages/kino_updates/widget/src/lib.rs | 9 +++-- kinode/src/terminal/mod.rs | 33 +++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/kinode/packages/kino_updates/widget/src/lib.rs b/kinode/packages/kino_updates/widget/src/lib.rs index b12093897..4e22ccb69 100644 --- a/kinode/packages/kino_updates/widget/src/lib.rs +++ b/kinode/packages/kino_updates/widget/src/lib.rs @@ -149,8 +149,13 @@ fn fetch_most_recent_blog_posts(n: usize) -> Vec { 60, vec![], ) { - Ok(response) => serde_json::from_slice::>(response.body()) - .expect("Invalid UTF-8 from kinode.org"), + Ok(response) => match serde_json::from_slice::>(response.body()) { + Ok(posts) => posts, + Err(e) => { + println!("Failed to parse blog posts: {e:?}"); + vec![] + } + }, Err(e) => { println!("Failed to fetch blog posts: {e:?}"); vec![] diff --git a/kinode/src/terminal/mod.rs b/kinode/src/terminal/mod.rs index 02c080e1b..05eae5e62 100644 --- a/kinode/src/terminal/mod.rs +++ b/kinode/src/terminal/mod.rs @@ -444,9 +444,9 @@ pub async fn terminal( )?; }, // - // BACKSPACE or DELETE: delete a single character at cursor + // BACKSPACE: delete a single character at cursor // - KeyCode::Backspace | KeyCode::Delete => { + KeyCode::Backspace => { if line_col == prompt_len { continue; } @@ -477,6 +477,35 @@ pub async fn terminal( )?; }, // + // DELETE: delete a single character at right of cursor + // + KeyCode::Delete => { + if line_col == current_line.len() { + continue; + } + current_line.remove(line_col); + if search_mode { + utils::execute_search( + &our, + &mut stdout, + ¤t_line, + prompt_len, + (win_cols, win_rows), + (line_col, cursor_col), + &mut command_history, + search_depth, + )?; + continue; + } + execute!( + stdout, + cursor::MoveTo(0, win_rows), + terminal::Clear(ClearType::CurrentLine), + Print(utils::truncate_in_place(¤t_line, prompt_len, win_cols, (line_col, cursor_col))), + cursor::MoveTo(cursor_col, win_rows), + )?; + } + // // LEFT: move cursor one spot left // KeyCode::Left => {