From 12f0ec33ba521d4d59f1998f496f4608d95c8798 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 30 Sep 2024 19:58:03 +0200 Subject: [PATCH 01/53] fix(homeserver): test configuration in linux --- pubky-homeserver/src/config.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/pubky-homeserver/src/config.rs b/pubky-homeserver/src/config.rs index 6065306..05bab18 100644 --- a/pubky-homeserver/src/config.rs +++ b/pubky-homeserver/src/config.rs @@ -155,7 +155,6 @@ impl Config { bootstrap, storage, db_map_size: 10485760, - dht_request_timeout: Some(Duration::from_millis(10)), ..Default::default() } } @@ -276,7 +275,6 @@ mod tests { testnet: true, bootstrap: testnet.bootstrap.into(), db_map_size: 10485760, - dht_request_timeout: Some(Duration::from_millis(10)), storage: config.storage.clone(), keypair: config.keypair.clone(), From 931e7319b51d672663027706019bd664597787ee Mon Sep 17 00:00:00 2001 From: SHAcollision Date: Fri, 20 Sep 2024 16:28:16 +0200 Subject: [PATCH 02/53] feat(homeserver): add dockerfile --- .dockerignore | 3 +++ Dockerfile | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0a5df56 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +/target +/docs +/.github \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1582693 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,56 @@ +# ======================== +# Build Stage +# ======================== +FROM rust:1.81.0-alpine3.20 AS builder + +# Install build dependencies, including static OpenSSL libraries +RUN apk add --no-cache \ + musl-dev \ + openssl-dev \ + openssl-libs-static \ + pkgconfig \ + build-base \ + curl + +# Set environment variables for static linking with OpenSSL +ENV OPENSSL_STATIC=yes +ENV OPENSSL_LIB_DIR=/usr/lib +ENV OPENSSL_INCLUDE_DIR=/usr/include + +# Add the MUSL target for static linking +RUN rustup target add x86_64-unknown-linux-musl + +# Set the working directory +WORKDIR /usr/src/app + +# Copy over Cargo.toml and Cargo.lock for dependency caching +COPY Cargo.toml Cargo.lock ./ + +# Copy over all the source code +COPY . . + +# Build the project in release mode for the MUSL target +RUN cargo build --release --bin pubky_homeserver --target x86_64-unknown-linux-musl + +# Strip the binary to reduce size +RUN strip target/x86_64-unknown-linux-musl/release/pubky_homeserver + +# ======================== +# Runtime Stage +# ======================== +FROM alpine:3.20 + +# Install runtime dependencies (only ca-certificates) +RUN apk add --no-cache ca-certificates + +# Copy the compiled binary from the builder stage +COPY --from=builder /usr/src/app/target/x86_64-unknown-linux-musl/release/pubky_homeserver /usr/local/bin/homeserver + +# Set the working directory +WORKDIR /usr/local/bin + +# Expose the port the homeserver listens on (should match that of config.toml) +EXPOSE 6287 + +# Set the default command to run the homeserver binary +CMD ["homeserver"] From 02bea3146c9f1abb75fb812c263c93b3709b453a Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 2 Oct 2024 17:17:01 +0300 Subject: [PATCH 03/53] examples(authn): add signup example --- Cargo.lock | 2 +- Cargo.toml | 2 +- examples/README.md | 6 +++ examples/authn/README.md | 13 +++++ examples/authn/signup.rs | 49 +++++++++++++++++++ .../src/main.rs => authenticator.rs} | 0 .../authenticator/Cargo.toml => cargo.toml} | 14 ++++-- 7 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 examples/README.md create mode 100644 examples/authn/README.md create mode 100644 examples/authn/signup.rs rename examples/authz/{authenticator/src/main.rs => authenticator.rs} (100%) rename examples/{authz/authenticator/Cargo.toml => cargo.toml} (55%) diff --git a/Cargo.lock b/Cargo.lock index d5af9d7..33dc3cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,7 +136,7 @@ dependencies = [ ] [[package]] -name = "authenticator" +name = "authn" version = "0.1.0" dependencies = [ "anyhow", diff --git a/Cargo.toml b/Cargo.toml index acd72a5..04d0af3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [ "pubky", "pubky-*", - "examples/authz/authenticator" + "examples" ] # See: https://github.com/rust-lang/rust/issues/90148#issuecomment-949194352 diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..dad4ccc --- /dev/null +++ b/examples/README.md @@ -0,0 +1,6 @@ +# Pubky examples + +Minimal examples for different flows and functions you might need to implement using Pubky. + +- [authentication](./authn/README.md): shows how to signup, signin or signout to and from a homeserver. +- [authorization flow](./authz/README.md): shows how to setup Pubky authz for a 3rd party application and how to implement an authenticator to sign in such app. diff --git a/examples/authn/README.md b/examples/authn/README.md new file mode 100644 index 0000000..162c19e --- /dev/null +++ b/examples/authn/README.md @@ -0,0 +1,13 @@ +# Authentication examples + +You can use these examples to test Signup or Signin to a provided homeserver using a keypair, +as opposed to using a the 3rd party [authorization flow](../authz). + + +## Usage + +### Signup + +```bash +cargo run --bin signup +``` diff --git a/examples/authn/signup.rs b/examples/authn/signup.rs new file mode 100644 index 0000000..350f760 --- /dev/null +++ b/examples/authn/signup.rs @@ -0,0 +1,49 @@ +use anyhow::Result; +use clap::Parser; +use pubky::PubkyClient; +use std::path::PathBuf; + +use pubky_common::{crypto::PublicKey}; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Cli { + /// Homeserver Pkarr Domain (for example `5jsjx1o6fzu6aeeo697r3i5rx15zq41kikcye8wtwdqm4nb4tryo`) + homeserver: String, + + /// Path to a recovery_file of the Pubky you want to sign in with + recovery_file: PathBuf, +} + +#[tokio::main] +async fn main() -> Result<()> { + let cli = Cli::parse(); + + let recovery_file = std::fs::read(&cli.recovery_file)?; + println!("\nSuccessfully opened recovery file"); + + let homeserver = cli.homeserver; + + let client = PubkyClient::builder().build() ; + + println!("Enter your recovery_file's passphrase to signup:"); + let passphrase = rpassword::read_password()?; + + let keypair = pubky_common::recovery_file::decrypt_recovery_file(&recovery_file, &passphrase)?; + + println!("Successfully decrypted the recovery file, signing up to the homeserver:"); + + client + .signup(&keypair, &PublicKey::try_from(homeserver).unwrap()) + .await?; + + println!("Successfully signed up. Checking session:"); + + let session = client.session(&keypair.public_key()).await?; + + println!("Successfully resolved current session at the homeserver."); + + println!("{:?}", session); + + Ok(()) +} diff --git a/examples/authz/authenticator/src/main.rs b/examples/authz/authenticator.rs similarity index 100% rename from examples/authz/authenticator/src/main.rs rename to examples/authz/authenticator.rs diff --git a/examples/authz/authenticator/Cargo.toml b/examples/cargo.toml similarity index 55% rename from examples/authz/authenticator/Cargo.toml rename to examples/cargo.toml index 932701b..a0e595f 100644 --- a/examples/authz/authenticator/Cargo.toml +++ b/examples/cargo.toml @@ -1,14 +1,22 @@ [package] -name = "authenticator" +name = "authn" version = "0.1.0" edition = "2021" +[[bin]] +name = "signup" +path = "./authn/signup.rs" + +[[bin]] +name = "authenticator" +path = "./authz/authenticator.rs" + [dependencies] anyhow = "1.0.86" base64 = "0.22.1" clap = { version = "4.5.16", features = ["derive"] } -pubky = { version = "0.1.0", path = "../../../pubky" } -pubky-common = { version = "0.1.0", path = "../../../pubky-common" } +pubky = { version = "0.1.0", path = "../pubky" } +pubky-common = { version = "0.1.0", path = "../pubky-common" } rpassword = "7.3.1" tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] } url = "2.5.2" From 0e90b8068ad67c81e4e1e45653294bd7eb24032b Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 2 Oct 2024 18:12:55 +0300 Subject: [PATCH 04/53] fix(examples): rename cargo.toml to Cargo.toml --- examples/cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/cargo.toml b/examples/cargo.toml index a0e595f..0c168f0 100644 --- a/examples/cargo.toml +++ b/examples/cargo.toml @@ -3,6 +3,7 @@ name = "authn" version = "0.1.0" edition = "2021" + [[bin]] name = "signup" path = "./authn/signup.rs" From 7485e41a77c7f20d7d13d7eff59573f568bd5236 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 2 Oct 2024 18:15:20 +0300 Subject: [PATCH 05/53] wip --- examples/{cargo.toml => Cargo.tomlx} | 1 - 1 file changed, 1 deletion(-) rename examples/{cargo.toml => Cargo.tomlx} (99%) diff --git a/examples/cargo.toml b/examples/Cargo.tomlx similarity index 99% rename from examples/cargo.toml rename to examples/Cargo.tomlx index 0c168f0..a0e595f 100644 --- a/examples/cargo.toml +++ b/examples/Cargo.tomlx @@ -3,7 +3,6 @@ name = "authn" version = "0.1.0" edition = "2021" - [[bin]] name = "signup" path = "./authn/signup.rs" From 2b15826fa3b7ce01cf52dc5c3b3d4a83e94b3d08 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 2 Oct 2024 18:15:42 +0300 Subject: [PATCH 06/53] fix(examples): rename cargo.toml to Cargo.toml --- examples/{Cargo.tomlx => Cargo.toml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{Cargo.tomlx => Cargo.toml} (100%) diff --git a/examples/Cargo.tomlx b/examples/Cargo.toml similarity index 100% rename from examples/Cargo.tomlx rename to examples/Cargo.toml From ba66c3ccd751dd31dac73cbbd198ef600d06aba5 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 2 Oct 2024 18:21:21 +0300 Subject: [PATCH 07/53] chore(examples): cargo fmt --- examples/authn/signup.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/authn/signup.rs b/examples/authn/signup.rs index 350f760..ecafae5 100644 --- a/examples/authn/signup.rs +++ b/examples/authn/signup.rs @@ -3,7 +3,7 @@ use clap::Parser; use pubky::PubkyClient; use std::path::PathBuf; -use pubky_common::{crypto::PublicKey}; +use pubky_common::crypto::PublicKey; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -24,7 +24,7 @@ async fn main() -> Result<()> { let homeserver = cli.homeserver; - let client = PubkyClient::builder().build() ; + let client = PubkyClient::builder().build(); println!("Enter your recovery_file's passphrase to signup:"); let passphrase = rpassword::read_password()?; @@ -33,9 +33,9 @@ async fn main() -> Result<()> { println!("Successfully decrypted the recovery file, signing up to the homeserver:"); - client - .signup(&keypair, &PublicKey::try_from(homeserver).unwrap()) - .await?; + client + .signup(&keypair, &PublicKey::try_from(homeserver).unwrap()) + .await?; println!("Successfully signed up. Checking session:"); From 27dd9930853c17c1729e42f35198b51fdcb4c2f0 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 3 Oct 2024 09:51:59 +0300 Subject: [PATCH 08/53] chore(homeserver): rename config.toml to config.example.toml --- .gitignore | 1 + pubky-homeserver/src/{config.toml => config.example.toml} | 0 2 files changed, 1 insertion(+) rename pubky-homeserver/src/{config.toml => config.example.toml} (100%) diff --git a/.gitignore b/.gitignore index 2f7896d..bab85c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ target/ +config.toml diff --git a/pubky-homeserver/src/config.toml b/pubky-homeserver/src/config.example.toml similarity index 100% rename from pubky-homeserver/src/config.toml rename to pubky-homeserver/src/config.example.toml From 7159a40987e78ed12cefde313a87cc455362eca8 Mon Sep 17 00:00:00 2001 From: James <74595920+catch-21@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:40:24 +0100 Subject: [PATCH 09/53] Update README.md --- pubky-homeserver/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubky-homeserver/README.md b/pubky-homeserver/README.md index d1799a2..f15c67a 100644 --- a/pubky-homeserver/README.md +++ b/pubky-homeserver/README.md @@ -5,7 +5,7 @@ Use `cargo run` ```bash -cargo run -- --config=./src/config.toml +cargo run -- --config=./src/config.rs ``` Or Build first then run from target. @@ -19,5 +19,5 @@ cargo build --release Run with an optional config file ```bash -../target/release/pubky-homeserver --config=./src/config.toml +../target/release/pubky_homeserver --config=./src/config.rs ``` From b543ffbb04e52e54a8cc48d600c93be25f2f0368 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 3 Oct 2024 16:32:09 +0300 Subject: [PATCH 10/53] fix(homeserver): detect requests in secure context for cookies --- Cargo.lock | 1 + pubky-homeserver/Cargo.toml | 1 + pubky-homeserver/src/routes/auth.rs | 47 +++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 33dc3cc..0d93a46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1563,6 +1563,7 @@ dependencies = [ "tower-http", "tracing", "tracing-subscriber", + "url", ] [[package]] diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index c8abfd5..ea55cf2 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -25,3 +25,4 @@ tower-cookies = "0.10.0" tower-http = { version = "0.5.2", features = ["cors", "trace"] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +url = "2.5.2" diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index dbcffe4..307ff2d 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -1,7 +1,7 @@ use axum::{ debug_handler, - extract::State, - http::{uri::Scheme, StatusCode, Uri}, + extract::{Host, State}, + http::StatusCode, response::IntoResponse, }; use axum_extra::{headers::UserAgent, TypedHeader}; @@ -25,12 +25,12 @@ pub async fn signup( State(state): State, user_agent: Option>, cookies: Cookies, - uri: Uri, + host: Host, body: Bytes, ) -> Result { // TODO: Verify invitation link. // TODO: add errors in case of already axisting user. - signin(State(state), user_agent, cookies, uri, body).await + signin(State(state), user_agent, cookies, host, body).await } pub async fn session( @@ -89,7 +89,7 @@ pub async fn signin( State(state): State, user_agent: Option>, cookies: Cookies, - uri: Uri, + Host(host): Host, body: Bytes, ) -> Result { let token = state.verifier.verify(&body)?; @@ -124,7 +124,8 @@ pub async fn signin( let mut cookie = Cookie::new(public_key.to_string(), session_secret); cookie.set_path("/"); - if *uri.scheme().unwrap_or(&Scheme::HTTP) == Scheme::HTTPS { + + if is_secure(&host) { cookie.set_secure(true); cookie.set_same_site(SameSite::None); } @@ -136,3 +137,37 @@ pub async fn signin( Ok(session) } + +/// Assuming that if the server is addressed by anything other than +/// localhost, or IP addresses, it is not addressed from a browser in an +/// secure (HTTPs) window, thus it no need to `secure` and `same_site=none` to cookies +fn is_secure(host: &str) -> bool { + url::Host::parse(host) + .map(|host| match host { + url::Host::Domain(domain) => domain != "localhost", + _ => false, + }) + .unwrap_or_default() +} + +#[cfg(test)] +mod tests { + use pkarr::Keypair; + + use super::*; + + #[test] + fn test_is_secure() { + assert_eq!(is_secure(""), false); + assert_eq!(is_secure("127.0.0.1"), false); + assert_eq!(is_secure("167.86.102.121"), false); + assert_eq!( + is_secure("[2001:0db8:0000:0000:0000:ff00:0042:8329]"), + false + ); + assert_eq!(is_secure("localhost"), false); + assert_eq!(is_secure("localhost:23423"), false); + assert_eq!(is_secure(&Keypair::random().public_key().to_string()), true); + assert_eq!(is_secure("example.com"), true); + } +} From 83ad51eb9275ad39a313eaf946641d1831dfa7ec Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 3 Oct 2024 16:46:29 +0300 Subject: [PATCH 11/53] fix(homeserver): set the well-known keypair at Config::testnet --- pubky-homeserver/src/config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pubky-homeserver/src/config.rs b/pubky-homeserver/src/config.rs index 05bab18..2b250e2 100644 --- a/pubky-homeserver/src/config.rs +++ b/pubky-homeserver/src/config.rs @@ -139,6 +139,7 @@ impl Config { port: 15411, dht_request_timeout: None, db_map_size: DEFAULT_MAP_SIZE, + keypair: Keypair::from_secret_key(&[0; 32]), ..Self::test(&testnet) } } From c77035c33aa661a567a7891489aaa02b6ee805f3 Mon Sep 17 00:00:00 2001 From: James <74595920+catch-21@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:09:18 +0100 Subject: [PATCH 12/53] Update README.md --- pubky-homeserver/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubky-homeserver/README.md b/pubky-homeserver/README.md index f15c67a..7b884d5 100644 --- a/pubky-homeserver/README.md +++ b/pubky-homeserver/README.md @@ -5,7 +5,7 @@ Use `cargo run` ```bash -cargo run -- --config=./src/config.rs +cargo run -- --config=./src/config.toml ``` Or Build first then run from target. @@ -19,5 +19,5 @@ cargo build --release Run with an optional config file ```bash -../target/release/pubky_homeserver --config=./src/config.rs +../target/release/pubky_homeserver --config=./src/config.toml ``` From affd589f1aa302bdf54a17ae8badbe238b5f749d Mon Sep 17 00:00:00 2001 From: nazeh Date: Mon, 7 Oct 2024 17:10:47 +0300 Subject: [PATCH 13/53] chore: clippy --- pubky-homeserver/src/routes/auth.rs | 19 ++++++++----------- pubky/src/shared/public.rs | 5 +---- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index 307ff2d..a4f36fc 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -158,16 +158,13 @@ mod tests { #[test] fn test_is_secure() { - assert_eq!(is_secure(""), false); - assert_eq!(is_secure("127.0.0.1"), false); - assert_eq!(is_secure("167.86.102.121"), false); - assert_eq!( - is_secure("[2001:0db8:0000:0000:0000:ff00:0042:8329]"), - false - ); - assert_eq!(is_secure("localhost"), false); - assert_eq!(is_secure("localhost:23423"), false); - assert_eq!(is_secure(&Keypair::random().public_key().to_string()), true); - assert_eq!(is_secure("example.com"), true); + assert!(!is_secure("")); + assert!(!is_secure("127.0.0.1")); + assert!(!is_secure("167.86.102.121")); + assert!(!is_secure("[2001:0db8:0000:0000:0000:ff00:0042:8329]")); + assert!(!is_secure("localhost")); + assert!(!is_secure("localhost:23423")); + assert!(is_secure(&Keypair::random().public_key().to_string())); + assert!(is_secure("example.com")); } } diff --git a/pubky/src/shared/public.rs b/pubky/src/shared/public.rs index becf2fb..21d3cbc 100644 --- a/pubky/src/shared/public.rs +++ b/pubky/src/shared/public.rs @@ -800,10 +800,7 @@ mod tests { let feed_url = format!("http://localhost:{}/events/", homeserver.port()); let response = client - .request( - Method::GET, - format!("{feed_url}").as_str().try_into().unwrap(), - ) + .request(Method::GET, feed_url.as_str().try_into().unwrap()) .send() .await .unwrap(); From 5a1a3da70bd86861e2d1c6ff8f06c5678d6ea6b6 Mon Sep 17 00:00:00 2001 From: nazeh Date: Mon, 7 Oct 2024 17:11:25 +0300 Subject: [PATCH 14/53] feat(homeserver): publish HTTPS instead of SVCB records --- pubky/src/shared/pkarr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubky/src/shared/pkarr.rs b/pubky/src/shared/pkarr.rs index 85055ef..48ea3ca 100644 --- a/pubky/src/shared/pkarr.rs +++ b/pubky/src/shared/pkarr.rs @@ -37,7 +37,7 @@ impl PubkyClient { "_pubky".try_into().unwrap(), pkarr::dns::CLASS::IN, 60 * 60, - pkarr::dns::rdata::RData::SVCB(svcb), + pkarr::dns::rdata::RData::HTTPS(svcb.into()), )); let signed_packet = SignedPacket::from_packet(keypair, &packet)?; From 76e95201383e3cc17333c98496220aa29e34a90e Mon Sep 17 00:00:00 2001 From: nazeh Date: Mon, 7 Oct 2024 17:17:58 +0300 Subject: [PATCH 15/53] feat(pubky): return cached packets if nothing else is available --- pubky/src/native.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pubky/src/native.rs b/pubky/src/native.rs index 81924ba..2b04804 100644 --- a/pubky/src/native.rs +++ b/pubky/src/native.rs @@ -11,7 +11,7 @@ use reqwest::{RequestBuilder, Response}; use tokio::sync::oneshot; use url::Url; -use pkarr::{Keypair, PkarrClientAsync}; +use pkarr::{mainline::MutableItem, Keypair, PkarrClientAsync}; use ::pkarr::{mainline::dht::Testnet, PkarrClient, PublicKey, SignedPacket}; @@ -240,7 +240,10 @@ impl PubkyClient { &self, public_key: &PublicKey, ) -> Result> { - Ok(self.pkarr.resolve(public_key).await?) + Ok(self.pkarr.resolve(public_key).await?.or(self + .pkarr + .cache() + .get(&MutableItem::target_from_key(public_key.as_bytes(), &None)))) } pub(crate) async fn pkarr_publish(&self, signed_packet: &SignedPacket) -> Result<()> { From fdfde60c72de5a635db9c62e1de091693e8b5abc Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 10 Oct 2024 13:28:58 +0300 Subject: [PATCH 16/53] examples(request): add a GET pubky:// url example --- Cargo.lock | 277 ++++++++++++++++++++++++++++++++++++- examples/Cargo.toml | 5 + examples/README.md | 1 + examples/request/README.md | 17 +++ examples/request/main.rs | 38 +++++ 5 files changed, 336 insertions(+), 2 deletions(-) create mode 100644 examples/request/README.md create mode 100644 examples/request/main.rs diff --git a/Cargo.lock b/Cargo.lock index 0d93a46..52ce106 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,6 +135,12 @@ dependencies = [ "critical-section", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "authn" version = "0.1.0" @@ -144,6 +150,7 @@ dependencies = [ "clap", "pubky", "pubky-common", + "reqwest", "rpassword", "tokio", "url", @@ -471,6 +478,22 @@ dependencies = [ "url", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.14" @@ -682,12 +705,37 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -712,6 +760,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -840,6 +903,25 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hash32" version = "0.2.1" @@ -1004,6 +1086,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2", "http", "http-body", "httparse", @@ -1033,6 +1116,22 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.9" @@ -1140,6 +1239,12 @@ dependencies = [ "libc", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "litrs" version = "0.4.1" @@ -1256,6 +1361,23 @@ dependencies = [ "getrandom", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1296,6 +1418,50 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "overload" version = "0.1.1" @@ -1442,6 +1608,12 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + [[package]] name = "poly1305" version = "0.8.0" @@ -1729,26 +1901,30 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", "cookie", "cookie_store", + "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -1760,7 +1936,9 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", + "system-configuration", "tokio", + "tokio-native-tls", "tokio-rustls", "tower-service", "url", @@ -1828,6 +2006,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "rustls" version = "0.23.13" @@ -1890,12 +2081,44 @@ dependencies = [ "cipher", ] +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "self_cell" version = "1.0.4" @@ -2163,6 +2386,40 @@ dependencies = [ "crossbeam-queue", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "thiserror" version = "1.0.64" @@ -2268,6 +2525,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.0" @@ -2522,6 +2789,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index a0e595f..ca8c035 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -11,12 +11,17 @@ path = "./authn/signup.rs" name = "authenticator" path = "./authz/authenticator.rs" +[[bin]] +name = "request" +path = "./request/main.rs" + [dependencies] anyhow = "1.0.86" base64 = "0.22.1" clap = { version = "4.5.16", features = ["derive"] } pubky = { version = "0.1.0", path = "../pubky" } pubky-common = { version = "0.1.0", path = "../pubky-common" } +reqwest = "0.12.8" rpassword = "7.3.1" tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] } url = "2.5.2" diff --git a/examples/README.md b/examples/README.md index dad4ccc..fb94edb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,5 +2,6 @@ Minimal examples for different flows and functions you might need to implement using Pubky. +- [request](./request/README.md): shows how to make direct HTTP requests to Pubky URLs. - [authentication](./authn/README.md): shows how to signup, signin or signout to and from a homeserver. - [authorization flow](./authz/README.md): shows how to setup Pubky authz for a 3rd party application and how to implement an authenticator to sign in such app. diff --git a/examples/request/README.md b/examples/request/README.md new file mode 100644 index 0000000..f072f77 --- /dev/null +++ b/examples/request/README.md @@ -0,0 +1,17 @@ +# Request + +Make HTTP requests over for Pubky authority URL. + +## Usage + +Request data from a Pubky's data storage. + +```bash +cargo run --bin request GET pubky:///pub/ +``` + +Or make a direct HTTP request. + +```bash +cargo run --bin request GET https:///[path] +``` diff --git a/examples/request/main.rs b/examples/request/main.rs new file mode 100644 index 0000000..69d5400 --- /dev/null +++ b/examples/request/main.rs @@ -0,0 +1,38 @@ +use anyhow::Result; +use clap::Parser; +use reqwest::Method; +use url::Url; + +use pubky::PubkyClient; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Cli { + /// HTTP method to use + method: Method, + /// Pubky or HTTPS url + url: Url, +} + +#[tokio::main] +async fn main() -> Result<()> { + let cli = Cli::parse(); + + let client = PubkyClient::builder().build(); + + match cli.url.scheme() { + "https" => { + unimplemented!(); + } + "pubky" => { + let response = client.get(cli.url).await.unwrap(); + + println!("Got a response: \n {:?}", response); + } + _ => { + panic!("Only https:// and pubky:// URL schemes are supported") + } + } + + Ok(()) +} From e749a685cd26357eea114eb8d902454da2beb07b Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 11 Oct 2024 16:31:12 +0300 Subject: [PATCH 17/53] feat(homeserver): set session cookies expiration date to two years --- pubky-homeserver/src/routes/auth.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index a4f36fc..034d29c 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -6,7 +6,13 @@ use axum::{ }; use axum_extra::{headers::UserAgent, TypedHeader}; use bytes::Bytes; -use tower_cookies::{cookie::SameSite, Cookie, Cookies}; +use tower_cookies::{ + cookie::{ + time::{Duration, OffsetDateTime}, + SameSite, + }, + Cookie, Cookies, +}; use pubky_common::{crypto::random_bytes, session::Session, timestamp::Timestamp}; @@ -124,6 +130,7 @@ pub async fn signin( let mut cookie = Cookie::new(public_key.to_string(), session_secret); cookie.set_path("/"); + cookie.set_expires(OffsetDateTime::now_utc() + Duration::weeks(104)); if is_secure(&host) { cookie.set_secure(true); From eacf942d08da76bb7a4fb8380054a664ccdfe547 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 11 Oct 2024 16:44:39 +0300 Subject: [PATCH 18/53] feat(homeserver): log cookies on auth --- pubky-homeserver/src/routes/auth.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index 034d29c..654c030 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -15,6 +15,7 @@ use tower_cookies::{ }; use pubky_common::{crypto::random_bytes, session::Session, timestamp::Timestamp}; +use tracing::debug; use crate::{ database::tables::{ @@ -138,6 +139,8 @@ pub async fn signin( } cookie.set_http_only(true); + debug!(?cookie, "Created, saved and sending a new Session cookie"); + cookies.add(cookie); wtxn.commit()?; From 379e921d186e22006deb51992552b69ea6529326 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 11 Oct 2024 17:22:27 +0300 Subject: [PATCH 19/53] Revert "feat(homeserver): set session cookies expiration date to two years" This reverts commit e749a685cd26357eea114eb8d902454da2beb07b. --- pubky-homeserver/src/routes/auth.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index 654c030..6a072ee 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -6,13 +6,7 @@ use axum::{ }; use axum_extra::{headers::UserAgent, TypedHeader}; use bytes::Bytes; -use tower_cookies::{ - cookie::{ - time::{Duration, OffsetDateTime}, - SameSite, - }, - Cookie, Cookies, -}; +use tower_cookies::{cookie::SameSite, Cookie, Cookies}; use pubky_common::{crypto::random_bytes, session::Session, timestamp::Timestamp}; use tracing::debug; @@ -131,7 +125,6 @@ pub async fn signin( let mut cookie = Cookie::new(public_key.to_string(), session_secret); cookie.set_path("/"); - cookie.set_expires(OffsetDateTime::now_utc() + Duration::weeks(104)); if is_secure(&host) { cookie.set_secure(true); From 29640eb702c9803894f534a2cdf63a48bd07b82b Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 11 Oct 2024 17:22:48 +0300 Subject: [PATCH 20/53] Revert "feat(homeserver): log cookies on auth" This reverts commit eacf942d08da76bb7a4fb8380054a664ccdfe547. --- pubky-homeserver/src/routes/auth.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index 6a072ee..a4f36fc 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -9,7 +9,6 @@ use bytes::Bytes; use tower_cookies::{cookie::SameSite, Cookie, Cookies}; use pubky_common::{crypto::random_bytes, session::Session, timestamp::Timestamp}; -use tracing::debug; use crate::{ database::tables::{ @@ -132,8 +131,6 @@ pub async fn signin( } cookie.set_http_only(true); - debug!(?cookie, "Created, saved and sending a new Session cookie"); - cookies.add(cookie); wtxn.commit()?; From 279db977438713d8eb6dc3855216ffd7ec33e065 Mon Sep 17 00:00:00 2001 From: nazeh Date: Mon, 14 Oct 2024 13:01:46 +0300 Subject: [PATCH 21/53] feat(homeserver): increase the file size limit to 100 Mb --- pubky-homeserver/src/routes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubky-homeserver/src/routes.rs b/pubky-homeserver/src/routes.rs index 7422f20..2105e86 100644 --- a/pubky-homeserver/src/routes.rs +++ b/pubky-homeserver/src/routes.rs @@ -30,7 +30,7 @@ fn base(state: AppState) -> Router { .layer(CookieManagerLayer::new()) // TODO: revisit if we enable streaming big payloads // TODO: maybe add to a separate router (drive router?). - .layer(DefaultBodyLimit::max(16 * 1024)) + .layer(DefaultBodyLimit::max(100 * 1024 * 1024)) .with_state(state) } From 3c5b123afd61c848baeb0c49d6995cea457a74ae Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 16 Oct 2024 16:26:35 +0300 Subject: [PATCH 22/53] feat(homeserver): handle streaming large files in and out --- Cargo.lock | 36 +- pubky-homeserver/src/database.rs | 48 +-- pubky-homeserver/src/database/tables/blobs.rs | 37 +- .../src/database/tables/entries.rs | 385 +++++++++++++----- pubky-homeserver/src/error.rs | 22 + pubky-homeserver/src/routes/public.rs | 94 +++-- pubky/src/shared/public.rs | 5 +- 7 files changed, 412 insertions(+), 215 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52ce106..1eab3be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -786,9 +786,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -801,9 +801,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -811,15 +811,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -828,15 +828,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -845,21 +845,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index e95d1d2..93d6311 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -1,4 +1,4 @@ -use std::fs; +use std::{fs, path::PathBuf}; use heed::{Env, EnvOpenOptions}; @@ -14,11 +14,16 @@ pub struct DB { pub(crate) env: Env, pub(crate) tables: Tables, pub(crate) config: Config, + pub(crate) buffers_dir: PathBuf, } impl DB { pub fn open(config: Config) -> anyhow::Result { - fs::create_dir_all(config.storage())?; + let buffers_dir = config.storage().clone().join("buffers"); + + // Cleanup buffers. + let _ = fs::remove_dir(&buffers_dir); + fs::create_dir_all(&buffers_dir)?; let env = unsafe { EnvOpenOptions::new() @@ -33,46 +38,9 @@ impl DB { env, tables, config, + buffers_dir, }; Ok(db) } } - -#[cfg(test)] -mod tests { - use bytes::Bytes; - use pkarr::{mainline::Testnet, Keypair}; - - use crate::config::Config; - - use super::DB; - - #[tokio::test] - async fn entries() { - let db = DB::open(Config::test(&Testnet::new(0))).unwrap(); - - let keypair = Keypair::random(); - let path = "/pub/foo.txt"; - - let (tx, rx) = flume::bounded::(0); - - let mut cloned = db.clone(); - let cloned_keypair = keypair.clone(); - - let done = tokio::task::spawn_blocking(move || { - cloned - .put_entry(&cloned_keypair.public_key(), path, rx) - .unwrap(); - }); - - tx.send(vec![1, 2, 3, 4, 5].into()).unwrap(); - drop(tx); - - done.await.unwrap(); - - let blob = db.get_blob(&keypair.public_key(), path).unwrap().unwrap(); - - assert_eq!(blob, Bytes::from(vec![1, 2, 3, 4, 5])); - } -} diff --git a/pubky-homeserver/src/database/tables/blobs.rs b/pubky-homeserver/src/database/tables/blobs.rs index c430a58..581bdb3 100644 --- a/pubky-homeserver/src/database/tables/blobs.rs +++ b/pubky-homeserver/src/database/tables/blobs.rs @@ -1,38 +1,23 @@ -use heed::{types::Bytes, Database}; -use pkarr::PublicKey; +use heed::{types::Bytes, Database, RoTxn}; +use pubky_common::timestamp::Timestamp; use crate::database::DB; -use super::entries::Entry; - /// hash of the blob => bytes. pub type BlobsTable = Database; pub const BLOBS_TABLE: &str = "blobs"; impl DB { - pub fn get_blob( + pub fn get_blob<'txn>( &self, - public_key: &PublicKey, - path: &str, - ) -> anyhow::Result> { - let rtxn = self.env.read_txn()?; - - let key = format!("{public_key}/{path}"); - - let result = if let Some(bytes) = self.tables.entries.get(&rtxn, &key)? { - let entry = Entry::deserialize(bytes)?; - - self.tables - .blobs - .get(&rtxn, entry.content_hash())? - .map(|blob| bytes::Bytes::from(blob[8..].to_vec())) - } else { - None - }; - - rtxn.commit()?; - - Ok(result) + rtxn: &'txn RoTxn, + timestamp: &Timestamp, + ) -> anyhow::Result> + 'txn> { + Ok(self + .tables + .blobs + .prefix_iter(rtxn, ×tamp.to_bytes())? + .map(|i| i.map(|(_, bytes)| bytes))) } } diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index b1c7039..6f7d097 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -1,6 +1,7 @@ use pkarr::PublicKey; use postcard::{from_bytes, to_allocvec}; use serde::{Deserialize, Serialize}; +use std::{fs::File, io::Read, path::PathBuf}; use tracing::instrument; use heed::{ @@ -23,74 +24,12 @@ pub type EntriesTable = Database; pub const ENTRIES_TABLE: &str = "entries"; impl DB { - pub fn put_entry( + pub fn write_entry( &mut self, public_key: &PublicKey, path: &str, - rx: flume::Receiver, - ) -> anyhow::Result<()> { - let mut wtxn = self.env.write_txn()?; - - let mut hasher = Hasher::new(); - let mut bytes = vec![]; - let mut length = 0; - - while let Ok(chunk) = rx.recv() { - hasher.update(&chunk); - bytes.extend_from_slice(&chunk); - length += chunk.len(); - } - - let hash = hasher.finalize(); - - let key = hash.as_bytes(); - - let mut bytes_with_ref_count = Vec::with_capacity(bytes.len() + 8); - bytes_with_ref_count.extend_from_slice(&u64::to_be_bytes(0)); - bytes_with_ref_count.extend_from_slice(&bytes); - - // TODO: For now, we set the first 8 bytes to a reference counter - let exists = self - .tables - .blobs - .get(&wtxn, key)? - .unwrap_or(bytes_with_ref_count.as_slice()); - - let new_count = u64::from_be_bytes(exists[0..8].try_into().unwrap()) + 1; - - bytes_with_ref_count[0..8].copy_from_slice(&u64::to_be_bytes(new_count)); - - self.tables - .blobs - .put(&mut wtxn, hash.as_bytes(), &bytes_with_ref_count)?; - - let mut entry = Entry::new(); - - entry.set_content_hash(hash); - entry.set_content_length(length); - - let key = format!("{public_key}/{path}"); - - self.tables - .entries - .put(&mut wtxn, &key, &entry.serialize())?; - - if path.starts_with("pub/") { - let url = format!("pubky://{key}"); - let event = Event::put(&url); - let value = event.serialize(); - - let key = entry.timestamp.to_string(); - - self.tables.events.put(&mut wtxn, &key, &value)?; - - // TODO: delete older events. - // TODO: move to events.rs - } - - wtxn.commit()?; - - Ok(()) + ) -> anyhow::Result { + EntryWriter::new(self, public_key, path) } pub fn delete_entry(&mut self, public_key: &PublicKey, path: &str) -> anyhow::Result { @@ -101,28 +40,20 @@ impl DB { let deleted = if let Some(bytes) = self.tables.entries.get(&wtxn, &key)? { let entry = Entry::deserialize(bytes)?; - let mut bytes_with_ref_count = self - .tables - .blobs - .get(&wtxn, entry.content_hash())? - .map_or(vec![], |s| s.to_vec()); + let mut deleted_chunks = false; - let arr: [u8; 8] = bytes_with_ref_count[0..8].try_into().unwrap_or([0; 8]); - let reference_count = u64::from_be_bytes(arr); - - let deleted_blobs = if reference_count > 1 { - // decrement reference count - - bytes_with_ref_count[0..8].copy_from_slice(&(reference_count - 1).to_be_bytes()); - - self.tables + { + let mut iter = self + .tables .blobs - .put(&mut wtxn, entry.content_hash(), &bytes_with_ref_count)?; + .prefix_iter_mut(&mut wtxn, &entry.timestamp.to_bytes())?; - true - } else { - self.tables.blobs.delete(&mut wtxn, entry.content_hash())? - }; + while iter.next().is_some() { + unsafe { + deleted_chunks = iter.del_current()?; + } + } + } let deleted_entry = self.tables.entries.delete(&mut wtxn, &key)?; @@ -137,11 +68,11 @@ impl DB { self.tables.events.put(&mut wtxn, &key, &value)?; - // TODO: delete older events. + // TODO: delete events older than a threshold. // TODO: move to events.rs } - deleted_entry && deleted_blobs + deleted_entry && deleted_chunks } else { false }; @@ -151,6 +82,21 @@ impl DB { Ok(deleted) } + pub fn get_entry( + &self, + txn: &RoTxn, + public_key: &PublicKey, + path: &str, + ) -> anyhow::Result> { + let key = format!("{public_key}/{path}"); + + if let Some(bytes) = self.tables.entries.get(txn, &key)? { + return Ok(Some(Entry::deserialize(bytes)?)); + } + + Ok(None) + } + pub fn contains_directory(&self, txn: &RoTxn, path: &str) -> anyhow::Result { Ok(self.tables.entries.get_greater_than(txn, path)?.is_some()) } @@ -268,13 +214,40 @@ pub struct Entry { version: usize, /// Modified at timestamp: Timestamp, - content_hash: [u8; 32], + content_hash: EntryHash, content_length: usize, content_type: String, // user_metadata: ? } -// TODO: get headers like Etag +#[derive(Clone, Debug, Eq, PartialEq)] +struct EntryHash(Hash); + +impl Default for EntryHash { + fn default() -> Self { + Self(Hash::from_bytes([0; 32])) + } +} + +impl Serialize for EntryHash { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let bytes = self.0.as_bytes(); + bytes.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for EntryHash { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let bytes: [u8; 32] = Deserialize::deserialize(deserializer)?; + Ok(Self(Hash::from_bytes(bytes))) + } +} impl Entry { pub fn new() -> Self { @@ -283,8 +256,13 @@ impl Entry { // === Setters === + pub fn set_timestamp(&mut self, timestamp: &Timestamp) -> &mut Self { + self.timestamp = timestamp.clone(); + self + } + pub fn set_content_hash(&mut self, content_hash: Hash) -> &mut Self { - content_hash.as_bytes().clone_into(&mut self.content_hash); + EntryHash(content_hash).clone_into(&mut self.content_hash); self } @@ -295,8 +273,20 @@ impl Entry { // === Getters === - pub fn content_hash(&self) -> &[u8; 32] { - &self.content_hash + pub fn timestamp(&self) -> &Timestamp { + &self.timestamp + } + + pub fn content_hash(&self) -> &Hash { + &self.content_hash.0 + } + + pub fn content_length(&self) -> usize { + self.content_length + } + + pub fn content_type(&self) -> &str { + &self.content_type } // === Public Method === @@ -313,3 +303,216 @@ impl Entry { from_bytes(bytes) } } + +pub struct EntryWriter<'db> { + db: &'db DB, + buffer: File, + hasher: Hasher, + buffer_path: PathBuf, + entry_key: String, + timestamp: Timestamp, + is_public: bool, +} + +impl<'db> EntryWriter<'db> { + pub fn new(db: &'db DB, public_key: &PublicKey, path: &str) -> anyhow::Result { + let hasher = Hasher::new(); + + let timestamp = Timestamp::now(); + + let buffer_path = db.buffers_dir.join(timestamp.to_string()); + + let buffer = File::create(&buffer_path)?; + + let entry_key = format!("{public_key}/{path}"); + + Ok(Self { + db, + buffer, + hasher, + buffer_path, + entry_key, + timestamp, + is_public: path.starts_with("pub/"), + }) + } + + /// Commit blob from the filesystem buffer to LMDB, + /// write the [Entry], and commit the write transaction. + pub fn commit(&self) -> anyhow::Result { + let hash = self.hasher.finalize(); + + // TODO: get the chunk size from the OS's page size + let chunk_size: usize = 2000; + + let mut buffer = File::open(&self.buffer_path)?; + + let mut wtxn = self.db.env.write_txn()?; + + let mut chunk_key = [0; 12]; + chunk_key[0..8].copy_from_slice(&self.timestamp.to_bytes()); + + let mut chunk_index: u32 = 0; + + loop { + let mut chunk = vec![0_u8; chunk_size]; + + let bytes_read = buffer.read(&mut chunk)?; + + if bytes_read == 0 { + break; // EOF reached + } + + chunk_key[8..].copy_from_slice(&chunk_index.to_be_bytes()); + + self.db + .tables + .blobs + .put(&mut wtxn, &chunk_key, &chunk[..bytes_read])?; + + chunk_index += 1; + } + + let mut entry = Entry::new(); + entry.set_timestamp(&self.timestamp); + + entry.set_content_hash(hash); + + let length = buffer.metadata()?.len(); + entry.set_content_length(length as usize); + + self.db + .tables + .entries + .put(&mut wtxn, &self.entry_key, &entry.serialize())?; + + // Write a public [Event]. + if self.is_public { + let url = format!("pubky://{}", self.entry_key); + let event = Event::put(&url); + let value = event.serialize(); + + let key = entry.timestamp.to_string(); + + self.db.tables.events.put(&mut wtxn, &key, &value)?; + + // TODO: delete events older than a threshold. + // TODO: move to events.rs + } + + wtxn.commit()?; + + std::fs::remove_file(&self.buffer_path)?; + + Ok(entry) + } +} + +impl<'db> std::io::Write for EntryWriter<'db> { + /// Write a chunk to a Filesystem based buffer. + #[inline] + fn write(&mut self, chunk: &[u8]) -> std::io::Result { + self.hasher.update(chunk); + self.buffer.write_all(chunk)?; + + Ok(chunk.len()) + } + + /// Does not do anything, you need to call [Self::commit] + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::io::Write; + + use bytes::Bytes; + use pkarr::{mainline::Testnet, Keypair}; + + use crate::config::Config; + + use super::DB; + + #[tokio::test] + async fn entries() { + let mut db = DB::open(Config::test(&Testnet::new(0))).unwrap(); + + let keypair = Keypair::random(); + let public_key = keypair.public_key(); + let path = "/pub/foo.txt"; + + let chunk = Bytes::from(vec![1, 2, 3, 4, 5]); + + let mut entry_writer = db.write_entry(&public_key, path).unwrap(); + entry_writer.write_all(&chunk).unwrap(); + entry_writer.commit().unwrap(); + + let rtxn = db.env.read_txn().unwrap(); + let entry = db.get_entry(&rtxn, &public_key, path).unwrap().unwrap(); + + assert_eq!( + entry.content_hash(), + &[ + 2, 79, 103, 192, 66, 90, 61, 192, 47, 186, 245, 140, 185, 61, 229, 19, 46, 61, 117, + 197, 25, 250, 160, 186, 218, 33, 73, 29, 136, 201, 112, 87 + ] + ); + + let mut blob = vec![]; + + { + let mut iter = db.get_blob(&rtxn, entry.timestamp()).unwrap(); + + while let Some(Ok(chunk)) = iter.next() { + blob.extend_from_slice(&chunk); + } + } + + assert_eq!(blob, vec![1, 2, 3, 4, 5]); + + rtxn.commit().unwrap(); + } + + #[tokio::test] + async fn chunked_entry() { + let mut db = DB::open(Config::test(&Testnet::new(0))).unwrap(); + + let keypair = Keypair::random(); + let public_key = keypair.public_key(); + let path = "/pub/foo.txt"; + + let chunk = Bytes::from(vec![0; 1024 * 1024]); + + let mut entry_writer = db.write_entry(&public_key, path).unwrap(); + entry_writer.write_all(&chunk).unwrap(); + entry_writer.commit().unwrap(); + + let rtxn = db.env.read_txn().unwrap(); + let entry = db.get_entry(&rtxn, &public_key, path).unwrap().unwrap(); + + assert_eq!( + entry.content_hash(), + &[ + 72, 141, 226, 2, 247, 59, 217, 118, 222, 78, 112, 72, 244, 225, 243, 154, 119, 109, + 134, 213, 130, 183, 52, 143, 245, 59, 244, 50, 185, 135, 252, 168 + ] + ); + + let mut blob = vec![]; + + { + let mut iter = db.get_blob(&rtxn, entry.timestamp()).unwrap(); + + while let Some(Ok(chunk)) = iter.next() { + blob.extend_from_slice(&chunk); + } + } + + assert_eq!(blob, vec![0; 1024 * 1024]); + + rtxn.commit().unwrap(); + } +} diff --git a/pubky-homeserver/src/error.rs b/pubky-homeserver/src/error.rs index 8aa58d2..1a8f8a0 100644 --- a/pubky-homeserver/src/error.rs +++ b/pubky-homeserver/src/error.rs @@ -5,6 +5,7 @@ use axum::{ http::StatusCode, response::IntoResponse, }; +use tokio::task::JoinError; use tracing::debug; pub type Result = core::result::Result; @@ -126,3 +127,24 @@ impl From> for Error { Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) } } + +impl From for Error { + fn from(error: flume::RecvError) -> Self { + debug!(?error); + Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) + } +} + +impl From for Error { + fn from(error: JoinError) -> Self { + debug!(?error); + Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) + } +} + +impl From for Error { + fn from(error: axum::http::Error) -> Self { + debug!(?error); + Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) + } +} diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index 8c6b2b9..1ddfe31 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -1,19 +1,23 @@ use axum::{ - body::{Body, Bytes}, + body::Body, + debug_handler, extract::State, http::{header, Response, StatusCode}, response::IntoResponse, }; use futures_util::stream::StreamExt; use pkarr::PublicKey; +use std::io::Write; use tower_cookies::Cookies; use crate::{ + database::tables::entries::Entry, error::{Error, Result}, extractors::{EntryPath, ListQueryParams, Pubky}, server::AppState, }; +#[debug_handler] pub async fn put( State(mut state): State, pubky: Pubky, @@ -22,37 +26,20 @@ pub async fn put( body: Body, ) -> Result { let public_key = pubky.public_key().clone(); - let path = path.as_str(); + let path = path.as_str().to_string(); - verify(path)?; - authorize(&mut state, cookies, &public_key, path)?; + verify(&path)?; + authorize(&mut state, cookies, &public_key, &path)?; + + let mut entry_writer = state.db.write_entry(&public_key, &path)?; let mut stream = body.into_data_stream(); - - let (tx, rx) = flume::bounded::(1); - - let path = path.to_string(); - - // TODO: refactor Database to clean up this scope. - let done = tokio::task::spawn_blocking(move || -> Result<()> { - // TODO: this is a blocking operation, which is ok for small - // payloads (we have 16 kb limit for now) but later we need - // to stream this to filesystem, and keep track of any failed - // writes to GC these files later. - - state.db.put_entry(&public_key, &path, rx)?; - - Ok(()) - }); - while let Some(next) = stream.next().await { let chunk = next?; - - tx.send(chunk)?; + entry_writer.write_all(&chunk)?; } - drop(tx); - done.await.expect("join error")?; + let _entry = entry_writer.commit()?; // TODO: return relevant headers, like Etag? @@ -66,9 +53,8 @@ pub async fn get( params: ListQueryParams, ) -> Result { verify(path.as_str())?; - let public_key = pubky.public_key(); - - let path = path.as_str(); + let public_key = pubky.public_key().clone(); + let path = path.as_str().to_string(); if path.ends_with('/') { let txn = state.db.env.read_txn()?; @@ -95,16 +81,49 @@ pub async fn get( return Ok(Response::builder() .status(StatusCode::OK) .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(vec.join("\n"))) - .unwrap()); + .body(Body::from(vec.join("\n")))?); } - // TODO: Enable streaming + let (entry_tx, entry_rx) = flume::bounded::>(1); + let (chunks_tx, chunks_rx) = flume::unbounded::, heed::Error>>(); - match state.db.get_blob(public_key, path) { - Err(error) => Err(error)?, - Ok(Some(bytes)) => Ok(Response::builder().body(Body::from(bytes)).unwrap()), - Ok(None) => Err(Error::new(StatusCode::NOT_FOUND, "File Not Found".into())), + tokio::task::spawn_blocking(move || -> anyhow::Result<()> { + let rtxn = state.db.env.read_txn()?; + + let option = state.db.get_entry(&rtxn, &public_key, &path)?; + + if let Some(entry) = option { + let iter = state.db.get_blob(&rtxn, entry.timestamp())?; + + entry_tx.send(Some(entry))?; + + for next in iter { + chunks_tx.send(next.map(|b| b.to_vec()))?; + } + }; + + entry_tx.send(None)?; + + Ok(()) + }); + + if let Some(entry) = entry_rx.recv_async().await? { + // TODO: add HEAD endpoint + // TODO: Enable seek API (range requests) + // TODO: Gzip? or brotli? + + Ok(Response::builder() + .status(StatusCode::OK) + .header(header::CONTENT_LENGTH, entry.content_length()) + .header(header::CONTENT_TYPE, entry.content_type()) + .header( + header::ETAG, + format!("\"{}\"", entry.content_hash().to_hex()), + ) + .body(Body::from_stream(chunks_rx.into_stream())) + .unwrap()) + } else { + Err(Error::with_status(StatusCode::NOT_FOUND))? } } @@ -120,14 +139,13 @@ pub async fn delete( authorize(&mut state, cookies, &public_key, path)?; verify(path)?; + // TODO: should we wrap this with `tokio::task::spawn_blocking` in case it takes too long? let deleted = state.db.delete_entry(&public_key, path)?; if !deleted { // TODO: if the path ends with `/` return a `CONFLICT` error? return Err(Error::with_status(StatusCode::NOT_FOUND)); - } - - // TODO: return relevant headers, like Etag? + }; Ok(()) } diff --git a/pubky/src/shared/public.rs b/pubky/src/shared/public.rs index 21d3cbc..da5c180 100644 --- a/pubky/src/shared/public.rs +++ b/pubky/src/shared/public.rs @@ -762,8 +762,9 @@ mod tests { ); } - let get = client.get(url.as_str()).await.unwrap(); - dbg!(get); + let resolved = client.get(url.as_str()).await.unwrap().unwrap(); + + assert_eq!(&resolved[..], &[0]); } #[tokio::test] From 8dde7b17da6a56fcf9fea8a28c6c9d7ee20ce5aa Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 16 Oct 2024 16:40:37 +0300 Subject: [PATCH 23/53] feat(homeserver): add Entry::read_content() method --- pubky-homeserver/src/database/tables/blobs.rs | 11 ++++++----- pubky-homeserver/src/database/tables/entries.rs | 12 ++++++++++-- pubky-homeserver/src/routes/public.rs | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/pubky-homeserver/src/database/tables/blobs.rs b/pubky-homeserver/src/database/tables/blobs.rs index 581bdb3..18ec724 100644 --- a/pubky-homeserver/src/database/tables/blobs.rs +++ b/pubky-homeserver/src/database/tables/blobs.rs @@ -1,23 +1,24 @@ use heed::{types::Bytes, Database, RoTxn}; -use pubky_common::timestamp::Timestamp; use crate::database::DB; -/// hash of the blob => bytes. +use super::entries::Entry; + +/// (entry timestamp | chunk_index BE) => bytes pub type BlobsTable = Database; pub const BLOBS_TABLE: &str = "blobs"; impl DB { - pub fn get_blob<'txn>( + pub fn read_entry_content<'txn>( &self, rtxn: &'txn RoTxn, - timestamp: &Timestamp, + entry: &Entry, ) -> anyhow::Result> + 'txn> { Ok(self .tables .blobs - .prefix_iter(rtxn, ×tamp.to_bytes())? + .prefix_iter(rtxn, &entry.timestamp().to_bytes())? .map(|i| i.map(|(_, bytes)| bytes))) } } diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index 6f7d097..52ec778 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -291,6 +291,14 @@ impl Entry { // === Public Method === + pub fn read_content<'txn>( + &self, + db: &'txn DB, + rtxn: &'txn RoTxn, + ) -> anyhow::Result> + 'txn> { + db.read_entry_content(rtxn, self) + } + pub fn serialize(&self) -> Vec { to_allocvec(self).expect("Session::serialize") } @@ -464,7 +472,7 @@ mod tests { let mut blob = vec![]; { - let mut iter = db.get_blob(&rtxn, entry.timestamp()).unwrap(); + let mut iter = entry.read_content(&db, &rtxn).unwrap(); while let Some(Ok(chunk)) = iter.next() { blob.extend_from_slice(&chunk); @@ -504,7 +512,7 @@ mod tests { let mut blob = vec![]; { - let mut iter = db.get_blob(&rtxn, entry.timestamp()).unwrap(); + let mut iter = entry.read_content(&db, &rtxn).unwrap(); while let Some(Ok(chunk)) = iter.next() { blob.extend_from_slice(&chunk); diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index 1ddfe31..50bddf3 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -93,7 +93,7 @@ pub async fn get( let option = state.db.get_entry(&rtxn, &public_key, &path)?; if let Some(entry) = option { - let iter = state.db.get_blob(&rtxn, entry.timestamp())?; + let iter = entry.read_content(&state.db, &rtxn)?; entry_tx.send(Some(entry))?; From fd88986a32df0862d2007b4bb43fa59f0117b7d5 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 16 Oct 2024 17:52:10 +0300 Subject: [PATCH 24/53] feat(homeserver): optimize chunk size for LMDB details --- Cargo.lock | 1 + pubky-homeserver/Cargo.toml | 1 + pubky-homeserver/src/database.rs | 17 ++++++++++ .../src/database/tables/entries.rs | 5 +-- pubky/src/shared/public.rs | 32 +++++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1eab3be..68f3ab5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1725,6 +1725,7 @@ dependencies = [ "futures-util", "heed", "hex", + "libc", "pkarr", "postcard", "pubky-common", diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index ea55cf2..bb1a908 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -15,6 +15,7 @@ flume = "0.11.0" futures-util = "0.3.30" heed = "0.20.3" hex = "0.4.3" +libc = "0.2.159" pkarr = { workspace = true } postcard = { version = "1.0.8", features = ["alloc"] } pubky-common = { version = "0.1.0", path = "../pubky-common" } diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index 93d6311..10fc3b4 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -15,6 +15,7 @@ pub struct DB { pub(crate) tables: Tables, pub(crate) config: Config, pub(crate) buffers_dir: PathBuf, + pub(crate) max_chunk_size: usize, } impl DB { @@ -39,8 +40,24 @@ impl DB { tables, config, buffers_dir, + max_chunk_size: max_chunk_size(), }; Ok(db) } } + +/// calculate optimal chunk size: +/// - https://lmdb.readthedocs.io/en/release/#storage-efficiency-limits +/// - https://github.com/lmdbjava/benchmarks/blob/master/results/20160710/README.md#test-2-determine-24816-kb-byte-values +fn max_chunk_size() -> usize { + let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }; + + // - 16 bytes Header per page (LMDB) + // - Each page has to contain 2 records + // - 8 bytes per record (LMDB) + // - 12 bytes key: + // - timestamp : 8 bytes + // - chunk index: 4 bytes + ((page_size - 16) / 2) - 8 - 12 +} diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index 52ec778..30b1043 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -350,9 +350,6 @@ impl<'db> EntryWriter<'db> { pub fn commit(&self) -> anyhow::Result { let hash = self.hasher.finalize(); - // TODO: get the chunk size from the OS's page size - let chunk_size: usize = 2000; - let mut buffer = File::open(&self.buffer_path)?; let mut wtxn = self.db.env.write_txn()?; @@ -363,7 +360,7 @@ impl<'db> EntryWriter<'db> { let mut chunk_index: u32 = 0; loop { - let mut chunk = vec![0_u8; chunk_size]; + let mut chunk = vec![0_u8; self.db.max_chunk_size]; let bytes_read = buffer.read(&mut chunk)?; diff --git a/pubky/src/shared/public.rs b/pubky/src/shared/public.rs index da5c180..81118f7 100644 --- a/pubky/src/shared/public.rs +++ b/pubky/src/shared/public.rs @@ -98,6 +98,7 @@ mod tests { use crate::*; + use bytes::Bytes; use pkarr::{mainline::Testnet, Keypair}; use pubky_homeserver::Homeserver; use reqwest::{Method, StatusCode}; @@ -819,4 +820,35 @@ mod tests { ] ) } + + #[tokio::test] + async fn stream() { + // TODO: test better streaming API + + let testnet = Testnet::new(10); + let server = Homeserver::start_test(&testnet).await.unwrap(); + + let client = PubkyClient::test(&testnet); + + let keypair = Keypair::random(); + + client.signup(&keypair, &server.public_key()).await.unwrap(); + + let url = format!("pubky://{}/pub/foo.txt", keypair.public_key()); + let url = url.as_str(); + + let bytes = Bytes::from(vec![0; 1024 * 1024]); + + client.put(url, &bytes).await.unwrap(); + + let response = client.get(url).await.unwrap().unwrap(); + + assert_eq!(response, bytes); + + client.delete(url).await.unwrap(); + + let response = client.get(url).await.unwrap(); + + assert_eq!(response, None); + } } From aace1aa8f03097b6552b472ea3fde0a0e8e96c0f Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 16 Oct 2024 18:11:36 +0300 Subject: [PATCH 25/53] chore(homeserver): remove debug_handler --- pubky-homeserver/src/routes/auth.rs | 2 -- pubky-homeserver/src/routes/public.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index a4f36fc..1075f48 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -1,5 +1,4 @@ use axum::{ - debug_handler, extract::{Host, State}, http::StatusCode, response::IntoResponse, @@ -20,7 +19,6 @@ use crate::{ server::AppState, }; -#[debug_handler] pub async fn signup( State(state): State, user_agent: Option>, diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index 50bddf3..bd61e23 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -1,6 +1,5 @@ use axum::{ body::Body, - debug_handler, extract::State, http::{header, Response, StatusCode}, response::IntoResponse, @@ -17,7 +16,6 @@ use crate::{ server::AppState, }; -#[debug_handler] pub async fn put( State(mut state): State, pubky: Pubky, From 060acb077fdc9920ee4856ad0996ed22621019f9 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 16 Oct 2024 18:41:49 +0300 Subject: [PATCH 26/53] fix(homeserver): fix chunk size calculation --- pubky-homeserver/src/database.rs | 4 ++-- pubky-homeserver/src/database/tables/entries.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index 10fc3b4..8ea4f48 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -55,9 +55,9 @@ fn max_chunk_size() -> usize { // - 16 bytes Header per page (LMDB) // - Each page has to contain 2 records - // - 8 bytes per record (LMDB) + // - 8 bytes per record (LMDB) (imperically, it seems to be 10 not 8) // - 12 bytes key: // - timestamp : 8 bytes // - chunk index: 4 bytes - ((page_size - 16) / 2) - 8 - 12 + ((page_size - 16) / 2) - (8 + 2) - 12 } diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index 30b1043..cf77b46 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -518,6 +518,10 @@ mod tests { assert_eq!(blob, vec![0; 1024 * 1024]); + let stats = db.tables.blobs.stat(&rtxn).unwrap(); + assert_eq!(stats.overflow_pages, 0); + assert_eq!(stats.leaf_pages, 128); + rtxn.commit().unwrap(); } } From ffd3cfbaac83e85a53eb8033fff3c75ae37639f7 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 16 Oct 2024 18:57:54 +0300 Subject: [PATCH 27/53] test(homeserver): remove system dependent test --- pubky-homeserver/src/database/tables/entries.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index cf77b46..1899578 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -520,7 +520,6 @@ mod tests { let stats = db.tables.blobs.stat(&rtxn).unwrap(); assert_eq!(stats.overflow_pages, 0); - assert_eq!(stats.leaf_pages, 128); rtxn.commit().unwrap(); } From 4067aedceebe70b5ab6b8d837910ea6e4b6e4acc Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 17 Oct 2024 17:28:16 +0300 Subject: [PATCH 28/53] feat: use pubky-timestamp --- Cargo.lock | 29 +-- pubky-common/Cargo.toml | 1 + pubky-common/src/auth.rs | 4 +- pubky-common/src/lib.rs | 5 +- pubky-common/src/session.rs | 2 +- pubky-common/src/timestamp.rs | 280 ---------------------------- pubky-homeserver/src/routes/auth.rs | 2 +- 7 files changed, 27 insertions(+), 296 deletions(-) delete mode 100644 pubky-common/src/timestamp.rs diff --git a/Cargo.lock b/Cargo.lock index 68f3ab5..be81384 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,12 +1405,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.1" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" -dependencies = [ - "portable-atomic", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -1625,12 +1622,6 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "portable-atomic" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" - [[package]] name = "postcard" version = "1.0.10" @@ -1705,11 +1696,27 @@ dependencies = [ "once_cell", "pkarr", "postcard", + "pubky-timestamp", "rand", "serde", "thiserror", ] +[[package]] +name = "pubky-timestamp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d018cd110531645acddc6493bb9f07d1f4869205d53ceea69f2331d5ff7af" +dependencies = [ + "base32", + "document-features", + "getrandom", + "httpdate", + "js-sys", + "once_cell", + "serde", +] + [[package]] name = "pubky_homeserver" version = "0.1.0" diff --git a/pubky-common/Cargo.toml b/pubky-common/Cargo.toml index 9676fba..48104cd 100644 --- a/pubky-common/Cargo.toml +++ b/pubky-common/Cargo.toml @@ -18,6 +18,7 @@ crypto_secretbox = { version = "0.1.1", features = ["std"] } argon2 = { version = "0.5.3", features = ["std"] } serde = { workspace = true, optional = true } +pubky-timestamp = { version = "0.1.0", features = ["full"] } [target.'cfg(target_arch = "wasm32")'.dependencies] js-sys = "0.3.69" diff --git a/pubky-common/src/auth.rs b/pubky-common/src/auth.rs index 866fe5e..118e328 100644 --- a/pubky-common/src/auth.rs +++ b/pubky-common/src/auth.rs @@ -76,7 +76,7 @@ impl AuthToken { let now = Timestamp::now(); // Chcek timestamp; - let diff = token.timestamp.difference(&now); + let diff = (token.timestamp.as_u64() - now.as_u64()) as i64; if diff > TIMESTAMP_WINDOW { return Err(Error::TooFarInTheFuture); } @@ -155,7 +155,7 @@ impl AuthVerifier { /// Remove all tokens older than two time intervals in the past. fn gc(&self) { - let threshold = ((Timestamp::now().into_inner() / TIME_INTERVAL) - 2).to_be_bytes(); + let threshold = ((Timestamp::now().as_u64() / TIME_INTERVAL) - 2).to_be_bytes(); let mut inner = self.seen.lock().unwrap(); diff --git a/pubky-common/src/lib.rs b/pubky-common/src/lib.rs index cfb56f2..9feccf4 100644 --- a/pubky-common/src/lib.rs +++ b/pubky-common/src/lib.rs @@ -4,4 +4,7 @@ pub mod crypto; pub mod namespaces; pub mod recovery_file; pub mod session; -pub mod timestamp; + +mod timestamp { + pub use pubky_timestamp::*; +} diff --git a/pubky-common/src/session.rs b/pubky-common/src/session.rs index 972652c..6b17735 100644 --- a/pubky-common/src/session.rs +++ b/pubky-common/src/session.rs @@ -26,7 +26,7 @@ impl Session { Self { version: 0, pubky: token.pubky().to_owned(), - created_at: Timestamp::now().into_inner(), + created_at: Timestamp::now().as_u64(), capabilities: token.capabilities().to_vec(), user_agent: user_agent.as_deref().unwrap_or("").to_string(), name: user_agent.as_deref().unwrap_or("").to_string(), diff --git a/pubky-common/src/timestamp.rs b/pubky-common/src/timestamp.rs deleted file mode 100644 index c3c9846..0000000 --- a/pubky-common/src/timestamp.rs +++ /dev/null @@ -1,280 +0,0 @@ -//! Strictly monotonic unix timestamp in microseconds - -use serde::{Deserialize, Serialize}; -use std::fmt::Display; -use std::{ - ops::{Add, Sub}, - sync::Mutex, -}; - -use once_cell::sync::Lazy; -use rand::Rng; - -#[cfg(not(target_arch = "wasm32"))] -use std::time::SystemTime; - -/// ~4% chance of none of 10 clocks have matching id. -const CLOCK_MASK: u64 = (1 << 8) - 1; -const TIME_MASK: u64 = !0 >> 8; - -pub struct TimestampFactory { - clock_id: u64, - last_time: u64, -} - -impl TimestampFactory { - pub fn new() -> Self { - Self { - clock_id: rand::thread_rng().gen::() & CLOCK_MASK, - last_time: system_time() & TIME_MASK, - } - } - - pub fn now(&mut self) -> Timestamp { - // Ensure strict monotonicity. - self.last_time = (system_time() & TIME_MASK).max(self.last_time + CLOCK_MASK + 1); - - // Add clock_id to the end of the timestamp - Timestamp(self.last_time | self.clock_id) - } -} - -impl Default for TimestampFactory { - fn default() -> Self { - Self::new() - } -} - -static DEFAULT_FACTORY: Lazy> = - Lazy::new(|| Mutex::new(TimestampFactory::default())); - -/// STrictly monotonic timestamp since [SystemTime::UNIX_EPOCH] in microseconds as u64. -/// -/// The purpose of this timestamp is to unique per "user", not globally, -/// it achieves this by: -/// 1. Override the last byte with a random `clock_id`, reducing the probability -/// of two matching timestamps across multiple machines/threads. -/// 2. Gurantee that the remaining 3 bytes are ever increasing (strictly monotonic) within -/// the same thread regardless of the wall clock value -/// -/// This timestamp is also serialized as BE bytes to remain sortable. -/// If a `utf-8` encoding is necessary, it is encoded as [base32::Alphabet::Crockford] -/// to act as a sortable Id. -/// -/// U64 of microseconds is valid for the next 500 thousand years! -#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)] -pub struct Timestamp(u64); - -impl Timestamp { - pub fn now() -> Self { - DEFAULT_FACTORY.lock().unwrap().now() - } - - /// Return big endian bytes - pub fn to_bytes(&self) -> [u8; 8] { - self.0.to_be_bytes() - } - - pub fn difference(&self, rhs: &Timestamp) -> i64 { - (self.0 as i64) - (rhs.0 as i64) - } - - pub fn into_inner(&self) -> u64 { - self.0 - } -} - -impl Default for Timestamp { - fn default() -> Self { - Timestamp::now() - } -} - -impl Display for Timestamp { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let bytes: [u8; 8] = self.into(); - f.write_str(&base32::encode(base32::Alphabet::Crockford, &bytes)) - } -} - -impl TryFrom for Timestamp { - type Error = TimestampError; - - fn try_from(value: String) -> Result { - match base32::decode(base32::Alphabet::Crockford, &value) { - Some(vec) => { - let bytes: [u8; 8] = vec - .try_into() - .map_err(|_| TimestampError::InvalidEncoding)?; - - Ok(bytes.into()) - } - None => Err(TimestampError::InvalidEncoding), - } - } -} - -impl TryFrom<&[u8]> for Timestamp { - type Error = TimestampError; - - fn try_from(bytes: &[u8]) -> Result { - let bytes: [u8; 8] = bytes - .try_into() - .map_err(|_| TimestampError::InvalidBytesLength(bytes.len()))?; - - Ok(bytes.into()) - } -} - -impl From<&Timestamp> for [u8; 8] { - fn from(timestamp: &Timestamp) -> Self { - timestamp.0.to_be_bytes() - } -} - -impl From<[u8; 8]> for Timestamp { - fn from(bytes: [u8; 8]) -> Self { - Self(u64::from_be_bytes(bytes)) - } -} - -// === U64 conversion === - -impl From for u64 { - fn from(value: Timestamp) -> Self { - value.into_inner() - } -} - -impl Add for &Timestamp { - type Output = Timestamp; - - fn add(self, rhs: u64) -> Self::Output { - Timestamp(self.0 + rhs) - } -} - -impl Sub for &Timestamp { - type Output = Timestamp; - - fn sub(self, rhs: u64) -> Self::Output { - Timestamp(self.0 - rhs) - } -} - -impl Serialize for Timestamp { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let bytes = self.to_bytes(); - bytes.serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for Timestamp { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let bytes: [u8; 8] = Deserialize::deserialize(deserializer)?; - Ok(Timestamp(u64::from_be_bytes(bytes))) - } -} - -#[cfg(not(target_arch = "wasm32"))] -/// Return the number of microseconds since [SystemTime::UNIX_EPOCH] -fn system_time() -> u64 { - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .expect("time drift") - .as_micros() as u64 -} - -#[cfg(target_arch = "wasm32")] -/// Return the number of microseconds since [SystemTime::UNIX_EPOCH] -pub fn system_time() -> u64 { - // Won't be an issue for more than 5000 years! - (js_sys::Date::now() as u64 ) - // Turn miliseconds to microseconds - * 1000 -} - -#[derive(thiserror::Error, Debug)] -pub enum TimestampError { - #[error("Invalid bytes length, Timestamp should be encoded as 8 bytes, got {0}")] - InvalidBytesLength(usize), - #[error("Invalid timestamp encoding")] - InvalidEncoding, -} - -#[cfg(test)] -mod tests { - use std::collections::HashSet; - - use super::*; - - #[test] - fn strictly_monotonic() { - const COUNT: usize = 100; - - let mut set = HashSet::with_capacity(COUNT); - let mut vec = Vec::with_capacity(COUNT); - - for _ in 0..COUNT { - let timestamp = Timestamp::now(); - - set.insert(timestamp.clone()); - vec.push(timestamp); - } - - let mut ordered = vec.clone(); - ordered.sort(); - - assert_eq!(set.len(), COUNT, "unique"); - assert_eq!(ordered, vec, "ordered"); - } - - #[test] - fn strings() { - const COUNT: usize = 100; - - let mut set = HashSet::with_capacity(COUNT); - let mut vec = Vec::with_capacity(COUNT); - - for _ in 0..COUNT { - let string = Timestamp::now().to_string(); - - set.insert(string.clone()); - vec.push(string) - } - - let mut ordered = vec.clone(); - ordered.sort(); - - assert_eq!(set.len(), COUNT, "unique"); - assert_eq!(ordered, vec, "ordered"); - } - - #[test] - fn to_from_string() { - let timestamp = Timestamp::now(); - let string = timestamp.to_string(); - let decoded: Timestamp = string.try_into().unwrap(); - - assert_eq!(decoded, timestamp) - } - - #[test] - fn serde() { - let timestamp = Timestamp::now(); - - let serialized = postcard::to_allocvec(×tamp).unwrap(); - - assert_eq!(serialized, timestamp.to_bytes()); - - let deserialized: Timestamp = postcard::from_bytes(&serialized).unwrap(); - - assert_eq!(deserialized, timestamp); - } -} diff --git a/pubky-homeserver/src/routes/auth.rs b/pubky-homeserver/src/routes/auth.rs index 1075f48..eaf3a57 100644 --- a/pubky-homeserver/src/routes/auth.rs +++ b/pubky-homeserver/src/routes/auth.rs @@ -104,7 +104,7 @@ pub async fn signin( &mut wtxn, public_key, &User { - created_at: Timestamp::now().into_inner(), + created_at: Timestamp::now().as_u64(), }, )?; } From ed06a4681efbc1ef424e3f1cba00e2c278015c47 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 17 Oct 2024 18:28:22 +0300 Subject: [PATCH 29/53] feat: add head endpoint --- Cargo.lock | 4 +-- pubky-common/Cargo.toml | 2 +- pubky-homeserver/src/routes.rs | 3 +- pubky-homeserver/src/routes/public.rs | 47 ++++++++++++++++++++++++++- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be81384..63a8c5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1704,9 +1704,9 @@ dependencies = [ [[package]] name = "pubky-timestamp" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d018cd110531645acddc6493bb9f07d1f4869205d53ceea69f2331d5ff7af" +checksum = "084b6e5bfcc186781b71257d636b660f20e94bb588c3ba52393fd9faf7a7bfda" dependencies = [ "base32", "document-features", diff --git a/pubky-common/Cargo.toml b/pubky-common/Cargo.toml index 48104cd..1220dff 100644 --- a/pubky-common/Cargo.toml +++ b/pubky-common/Cargo.toml @@ -18,7 +18,7 @@ crypto_secretbox = { version = "0.1.1", features = ["std"] } argon2 = { version = "0.5.3", features = ["std"] } serde = { workspace = true, optional = true } -pubky-timestamp = { version = "0.1.0", features = ["full"] } +pubky-timestamp = { version = "0.2.0", features = ["full"] } [target.'cfg(target_arch = "wasm32")'.dependencies] js-sys = "0.3.69" diff --git a/pubky-homeserver/src/routes.rs b/pubky-homeserver/src/routes.rs index 2105e86..6404ffb 100644 --- a/pubky-homeserver/src/routes.rs +++ b/pubky-homeserver/src/routes.rs @@ -1,6 +1,6 @@ use axum::{ extract::DefaultBodyLimit, - routing::{delete, get, post, put}, + routing::{delete, get, head, post, put}, Router, }; use tower_cookies::CookieManagerLayer; @@ -25,6 +25,7 @@ fn base(state: AppState) -> Router { .route("/:pubky/session", delete(auth::signout)) .route("/:pubky/*path", put(public::put)) .route("/:pubky/*path", get(public::get)) + .route("/:pubky/*path", head(public::head)) .route("/:pubky/*path", delete(public::delete)) .route("/events/", get(feed::feed)) .layer(CookieManagerLayer::new()) diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index bd61e23..14c3957 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -1,7 +1,7 @@ use axum::{ body::Body, extract::State, - http::{header, Response, StatusCode}, + http::{header, HeaderMap, HeaderValue, Response, StatusCode}, response::IntoResponse, }; use futures_util::stream::StreamExt; @@ -125,6 +125,26 @@ pub async fn get( } } +pub async fn head( + State(state): State, + pubky: Pubky, + path: EntryPath, +) -> Result { + verify(path.as_str())?; + + let rtxn = state.db.env.read_txn()?; + + match state + .db + .get_entry(&rtxn, pubky.public_key(), path.as_str())? + .as_ref() + .map(HeaderMap::from) + { + Some(headers) => Ok(headers), + None => Err(Error::with_status(StatusCode::NOT_FOUND)), + } +} + pub async fn delete( State(mut state): State, pubky: Pubky, @@ -188,3 +208,28 @@ fn verify(path: &str) -> Result<()> { Ok(()) } + +impl From<&Entry> for HeaderMap { + fn from(entry: &Entry) -> Self { + let mut headers = HeaderMap::new(); + headers.insert(header::CONTENT_LENGTH, entry.content_length().into()); + headers.insert(header::LAST_MODIFIED, entry.timestamp().format_http_date()); + headers.insert( + header::CONTENT_TYPE, + // TODO: when setting content type from user input, we should validate it as a HeaderValue + entry + .content_type() + .try_into() + .or(HeaderValue::from_str("")) + .expect("valid header value"), + ); + headers.insert( + header::ETAG, + format!("\"{}\"", entry.content_hash()) + .try_into() + .expect("hex string is valid"), + ); + + headers + } +} From 866a476d15ae85a3b11648146c93648e6e52c230 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 17 Oct 2024 18:55:35 +0300 Subject: [PATCH 30/53] fix: multiple issues after updating timestamp --- Cargo.lock | 123 +++++++++++++------------- Cargo.toml | 2 +- pubky-common/Cargo.toml | 11 +-- pubky-common/src/auth.rs | 4 +- pubky-common/src/lib.rs | 2 +- pubky-homeserver/src/routes/feed.rs | 18 ++-- pubky-homeserver/src/routes/public.rs | 6 +- 7 files changed, 78 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63a8c5a..9199a20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -362,9 +362,9 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.22" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "shlex", ] @@ -388,9 +388,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -398,9 +398,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -520,9 +520,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "critical-section" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-queue" @@ -899,9 +899,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" @@ -933,9 +933,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "headers" @@ -1067,9 +1067,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1079,9 +1079,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1173,9 +1173,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", @@ -1192,9 +1192,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is_terminal_polyfill" @@ -1210,9 +1210,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1225,9 +1225,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" [[package]] name = "libredox" @@ -1280,9 +1280,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" [[package]] name = "mainline" @@ -1396,9 +1396,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] @@ -1417,9 +1417,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags", "cfg-if", @@ -1449,9 +1449,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -1572,7 +1572,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkarr" version = "2.2.0" -source = "git+https://github.com/Pubky/pkarr?branch=serde#680ec9303f5f3ee4b40dc53c0071c4088d4eb6ff" +source = "git+https://github.com/Pubky/pkarr?branch=serde#61232ffa1b81be20530dfb81fe31273e2c860977" dependencies = [ "base32", "bytes", @@ -1652,9 +1652,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -2029,9 +2029,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "once_cell", "ring", @@ -2043,19 +2043,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -2070,9 +2069,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -2739,9 +2738,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -2826,9 +2825,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -2837,9 +2836,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -2852,9 +2851,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -2864,9 +2863,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2874,9 +2873,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -2887,15 +2886,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 04d0af3..1e59b0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ resolver = "2" [workspace.dependencies] -pkarr = { git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["async"] } +pkarr = { git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["async", "serde"] } serde = { version = "^1.0.209", features = ["derive"] } [profile.release] diff --git a/pubky-common/Cargo.toml b/pubky-common/Cargo.toml index 1220dff..faf1d3d 100644 --- a/pubky-common/Cargo.toml +++ b/pubky-common/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] base32 = "0.5.0" blake3 = "1.5.1" -ed25519-dalek = "2.1.1" +ed25519-dalek = { version = "2.1.1", features = ["serde"] } once_cell = "1.19.0" pkarr = { workspace = true } rand = "0.8.5" @@ -17,7 +17,7 @@ postcard = { version = "1.0.8", features = ["alloc"] } crypto_secretbox = { version = "0.1.1", features = ["std"] } argon2 = { version = "0.5.3", features = ["std"] } -serde = { workspace = true, optional = true } +serde = { workspace = true } pubky-timestamp = { version = "0.2.0", features = ["full"] } [target.'cfg(target_arch = "wasm32")'.dependencies] @@ -25,10 +25,3 @@ js-sys = "0.3.69" [dev-dependencies] postcard = "1.0.8" - -[features] - -serde = ["dep:serde", "ed25519-dalek/serde", "pkarr/serde"] -full = ['serde'] - -default = ['full'] diff --git a/pubky-common/src/auth.rs b/pubky-common/src/auth.rs index 118e328..082b8e8 100644 --- a/pubky-common/src/auth.rs +++ b/pubky-common/src/auth.rs @@ -76,7 +76,7 @@ impl AuthToken { let now = Timestamp::now(); // Chcek timestamp; - let diff = (token.timestamp.as_u64() - now.as_u64()) as i64; + let diff = token.timestamp.as_u64() as i64 - now.as_u64() as i64; if diff > TIMESTAMP_WINDOW { return Err(Error::TooFarInTheFuture); } @@ -235,7 +235,7 @@ mod tests { let verifier = AuthVerifier::default(); - let timestamp = (&Timestamp::now()) - (TIMESTAMP_WINDOW as u64); + let timestamp = (Timestamp::now()) - (TIMESTAMP_WINDOW as u64); let mut signable = vec![]; signable.extend_from_slice(signer.public_key().as_bytes()); diff --git a/pubky-common/src/lib.rs b/pubky-common/src/lib.rs index 9feccf4..b19a187 100644 --- a/pubky-common/src/lib.rs +++ b/pubky-common/src/lib.rs @@ -5,6 +5,6 @@ pub mod namespaces; pub mod recovery_file; pub mod session; -mod timestamp { +pub mod timestamp { pub use pubky_timestamp::*; } diff --git a/pubky-homeserver/src/routes/feed.rs b/pubky-homeserver/src/routes/feed.rs index 6271aeb..a54b8a5 100644 --- a/pubky-homeserver/src/routes/feed.rs +++ b/pubky-homeserver/src/routes/feed.rs @@ -4,7 +4,7 @@ use axum::{ http::{header, Response, StatusCode}, response::IntoResponse, }; -use pubky_common::timestamp::{Timestamp, TimestampError}; +use pubky_common::timestamp::Timestamp; use crate::{ error::{Error, Result}, @@ -17,17 +17,11 @@ pub async fn feed( params: ListQueryParams, ) -> Result { if let Some(ref cursor) = params.cursor { - if let Err(timestmap_error) = Timestamp::try_from(cursor.to_string()) { - let cause = match timestmap_error { - TimestampError::InvalidEncoding => { - "Cursor should be valid base32 Crockford encoding of a timestamp" - } - TimestampError::InvalidBytesLength(size) => { - &format!("Cursor should be 13 characters long, got: {size}") - } - }; - - Err(Error::new(StatusCode::BAD_REQUEST, cause.into()))? + if Timestamp::try_from(cursor.to_string()).is_err() { + Err(Error::new( + StatusCode::BAD_REQUEST, + "Cursor should be valid base32 Crockford encoding of a timestamp".into(), + ))? } } diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index 14c3957..0e91ae9 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -213,7 +213,11 @@ impl From<&Entry> for HeaderMap { fn from(entry: &Entry) -> Self { let mut headers = HeaderMap::new(); headers.insert(header::CONTENT_LENGTH, entry.content_length().into()); - headers.insert(header::LAST_MODIFIED, entry.timestamp().format_http_date()); + headers.insert( + header::LAST_MODIFIED, + HeaderValue::from_str(&entry.timestamp().format_http_date()) + .expect("http date is valid header value"), + ); headers.insert( header::CONTENT_TYPE, // TODO: when setting content type from user input, we should validate it as a HeaderValue From 583ed039b5405072507d74d36f54fb43b27bf257 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 17 Oct 2024 20:57:30 +0300 Subject: [PATCH 31/53] feat(homeserver): support if-modified-since header in GET requests --- Cargo.lock | 2 + pubky-homeserver/Cargo.toml | 4 + .../src/database/tables/entries.rs | 36 ++++++--- pubky-homeserver/src/routes/public.rs | 77 ++++++++++++++++--- pubky-homeserver/src/server.rs | 5 ++ 5 files changed, 101 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9199a20..746cb90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1732,10 +1732,12 @@ dependencies = [ "futures-util", "heed", "hex", + "httpdate", "libc", "pkarr", "postcard", "pubky-common", + "reqwest", "serde", "tokio", "toml", diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index bb1a908..7cfaa34 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -15,6 +15,7 @@ flume = "0.11.0" futures-util = "0.3.30" heed = "0.20.3" hex = "0.4.3" +httpdate = "1.0.3" libc = "0.2.159" pkarr = { workspace = true } postcard = { version = "1.0.8", features = ["alloc"] } @@ -27,3 +28,6 @@ tower-http = { version = "0.5.2", features = ["cors", "trace"] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } url = "2.5.2" + +[dev-dependencies] +reqwest = "0.12.8" diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index 1899578..9928c34 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -1,7 +1,11 @@ use pkarr::PublicKey; use postcard::{from_bytes, to_allocvec}; use serde::{Deserialize, Serialize}; -use std::{fs::File, io::Read, path::PathBuf}; +use std::{ + fs::File, + io::{Read, Write}, + path::PathBuf, +}; use tracing::instrument; use heed::{ @@ -345,6 +349,14 @@ impl<'db> EntryWriter<'db> { }) } + /// Same ase [EntryWriter::write_all] but returns a Result of a mutable reference of itself + /// to enable chaining with [Self::commit]. + pub fn update(&mut self, chunk: &[u8]) -> Result<&mut Self, std::io::Error> { + self.write_all(chunk)?; + + Ok(self) + } + /// Commit blob from the filesystem buffer to LMDB, /// write the [Entry], and commit the write transaction. pub fn commit(&self) -> anyhow::Result { @@ -432,8 +444,6 @@ impl<'db> std::io::Write for EntryWriter<'db> { #[cfg(test)] mod tests { - use std::io::Write; - use bytes::Bytes; use pkarr::{mainline::Testnet, Keypair}; @@ -442,7 +452,7 @@ mod tests { use super::DB; #[tokio::test] - async fn entries() { + async fn entries() -> anyhow::Result<()> { let mut db = DB::open(Config::test(&Testnet::new(0))).unwrap(); let keypair = Keypair::random(); @@ -451,9 +461,9 @@ mod tests { let chunk = Bytes::from(vec![1, 2, 3, 4, 5]); - let mut entry_writer = db.write_entry(&public_key, path).unwrap(); - entry_writer.write_all(&chunk).unwrap(); - entry_writer.commit().unwrap(); + db.write_entry(&public_key, path)? + .update(&chunk)? + .commit()?; let rtxn = db.env.read_txn().unwrap(); let entry = db.get_entry(&rtxn, &public_key, path).unwrap().unwrap(); @@ -479,10 +489,12 @@ mod tests { assert_eq!(blob, vec![1, 2, 3, 4, 5]); rtxn.commit().unwrap(); + + Ok(()) } #[tokio::test] - async fn chunked_entry() { + async fn chunked_entry() -> anyhow::Result<()> { let mut db = DB::open(Config::test(&Testnet::new(0))).unwrap(); let keypair = Keypair::random(); @@ -491,9 +503,9 @@ mod tests { let chunk = Bytes::from(vec![0; 1024 * 1024]); - let mut entry_writer = db.write_entry(&public_key, path).unwrap(); - entry_writer.write_all(&chunk).unwrap(); - entry_writer.commit().unwrap(); + db.write_entry(&public_key, path)? + .update(&chunk)? + .commit()?; let rtxn = db.env.read_txn().unwrap(); let entry = db.get_entry(&rtxn, &public_key, path).unwrap().unwrap(); @@ -522,5 +534,7 @@ mod tests { assert_eq!(stats.overflow_pages, 0); rtxn.commit().unwrap(); + + Ok(()) } } diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index 0e91ae9..d55c0c5 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -5,8 +5,9 @@ use axum::{ response::IntoResponse, }; use futures_util::stream::StreamExt; +use httpdate::HttpDate; use pkarr::PublicKey; -use std::io::Write; +use std::{io::Write, str::FromStr}; use tower_cookies::Cookies; use crate::{ @@ -46,6 +47,7 @@ pub async fn put( pub async fn get( State(state): State, + headers: HeaderMap, pubky: Pubky, path: EntryPath, params: ListQueryParams, @@ -106,20 +108,27 @@ pub async fn get( }); if let Some(entry) = entry_rx.recv_async().await? { - // TODO: add HEAD endpoint // TODO: Enable seek API (range requests) // TODO: Gzip? or brotli? - Ok(Response::builder() - .status(StatusCode::OK) - .header(header::CONTENT_LENGTH, entry.content_length()) - .header(header::CONTENT_TYPE, entry.content_type()) - .header( - header::ETAG, - format!("\"{}\"", entry.content_hash().to_hex()), - ) - .body(Body::from_stream(chunks_rx.into_stream())) - .unwrap()) + let mut response = HeaderMap::from(&entry).into_response(); + + // Handle IF_MODIFIED_SINCE + if let Some(condition_http_date) = headers + .get(header::IF_MODIFIED_SINCE) + .and_then(|h| h.to_str().ok()) + .and_then(|s| HttpDate::from_str(s).ok()) + { + let entry_http_date: HttpDate = entry.timestamp().to_owned().into(); + + if condition_http_date >= entry_http_date { + *response.status_mut() = StatusCode::NOT_MODIFIED; + } + } else { + *response.body_mut() = Body::from_stream(chunks_rx.into_stream()); + }; + + Ok(response) } else { Err(Error::with_status(StatusCode::NOT_FOUND))? } @@ -237,3 +246,47 @@ impl From<&Entry> for HeaderMap { headers } } + +#[cfg(test)] +mod tests { + use axum::http::header; + use pkarr::{mainline::Testnet, Keypair}; + use reqwest::{self, Method, StatusCode}; + + use crate::Homeserver; + + #[tokio::test] + async fn if_last_modified() -> anyhow::Result<()> { + let testnet = Testnet::new(3); + let mut server = Homeserver::start_test(&testnet).await?; + + let public_key = Keypair::random().public_key(); + + let data = &[1, 2, 3, 4, 5]; + + server + .database_mut() + .write_entry(&public_key, "pub/foo")? + .update(data)? + .commit()?; + + let client = reqwest::Client::builder().build()?; + + let url = format!("http://localhost:{}/{public_key}/pub/foo", server.port()); + + let response = client.request(Method::GET, &url).send().await?; + + let response = client + .request(Method::GET, &url) + .header( + header::IF_MODIFIED_SINCE, + response.headers().get(header::LAST_MODIFIED).unwrap(), + ) + .send() + .await?; + + assert_eq!(response.status(), StatusCode::NOT_MODIFIED); + + Ok(()) + } +} diff --git a/pubky-homeserver/src/server.rs b/pubky-homeserver/src/server.rs index d44d346..c3f8719 100644 --- a/pubky-homeserver/src/server.rs +++ b/pubky-homeserver/src/server.rs @@ -108,6 +108,11 @@ impl Homeserver { self.state.config.keypair().public_key() } + #[cfg(test)] + pub(crate) fn database_mut(&mut self) -> &mut DB { + &mut self.state.db + } + // === Public Methods === /// Shutdown the server and wait for all tasks to complete. From fc6d26e821889023c31434bbdacbe777d9b15940 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 17 Oct 2024 21:26:29 +0300 Subject: [PATCH 32/53] feat(homeserver): support if-modified-since header in HEAD requests --- pubky-homeserver/src/routes/public.rs | 72 ++++++++++++++++++--------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index d55c0c5..43e120e 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -1,5 +1,6 @@ use axum::{ body::Body, + debug_handler, extract::State, http::{header, HeaderMap, HeaderValue, Response, StatusCode}, response::IntoResponse, @@ -45,6 +46,7 @@ pub async fn put( Ok(()) } +#[debug_handler] pub async fn get( State(state): State, headers: HeaderMap, @@ -107,7 +109,38 @@ pub async fn get( Ok(()) }); - if let Some(entry) = entry_rx.recv_async().await? { + get_entry( + headers, + entry_rx.recv_async().await?, + Some(Body::from_stream(chunks_rx.into_stream())), + ) +} + +pub async fn head( + State(state): State, + headers: HeaderMap, + pubky: Pubky, + path: EntryPath, +) -> Result { + verify(path.as_str())?; + + let rtxn = state.db.env.read_txn()?; + + get_entry( + headers, + state + .db + .get_entry(&rtxn, pubky.public_key(), path.as_str())?, + None, + ) +} + +pub fn get_entry( + headers: HeaderMap, + entry: Option, + body: Option, +) -> Result> { + if let Some(entry) = entry { // TODO: Enable seek API (range requests) // TODO: Gzip? or brotli? @@ -124,8 +157,10 @@ pub async fn get( if condition_http_date >= entry_http_date { *response.status_mut() = StatusCode::NOT_MODIFIED; } - } else { - *response.body_mut() = Body::from_stream(chunks_rx.into_stream()); + }; + + if let Some(body) = body { + *response.body_mut() = body; }; Ok(response) @@ -134,26 +169,6 @@ pub async fn get( } } -pub async fn head( - State(state): State, - pubky: Pubky, - path: EntryPath, -) -> Result { - verify(path.as_str())?; - - let rtxn = state.db.env.read_txn()?; - - match state - .db - .get_entry(&rtxn, pubky.public_key(), path.as_str())? - .as_ref() - .map(HeaderMap::from) - { - Some(headers) => Ok(headers), - None => Err(Error::with_status(StatusCode::NOT_FOUND)), - } -} - pub async fn delete( State(mut state): State, pubky: Pubky, @@ -287,6 +302,17 @@ mod tests { assert_eq!(response.status(), StatusCode::NOT_MODIFIED); + let response = client + .request(Method::HEAD, &url) + .header( + header::IF_MODIFIED_SINCE, + response.headers().get(header::LAST_MODIFIED).unwrap(), + ) + .send() + .await?; + + assert_eq!(response.status(), StatusCode::NOT_MODIFIED); + Ok(()) } } From 6592b87fcd4e177bde9bd00a495c829af277765f Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 17 Oct 2024 21:40:56 +0300 Subject: [PATCH 33/53] feat(homeserver): support if-none-match header in GET and HEAD requests --- pubky-homeserver/src/routes/public.rs | 62 +++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index 43e120e..3b9963f 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -159,6 +159,22 @@ pub fn get_entry( } }; + // Handle IF_NONE_MATCH + if let Some(str) = headers + .get(header::IF_NONE_MATCH) + .and_then(|h| h.to_str().ok()) + { + let etag = format!("\"{}\"", entry.content_hash()); + if str + .trim() + .split(',') + .collect::>() + .contains(&etag.as_str()) + { + *response.status_mut() = StatusCode::NOT_MODIFIED; + }; + } + if let Some(body) = body { *response.body_mut() = body; }; @@ -315,4 +331,50 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn if_none_match() -> anyhow::Result<()> { + let testnet = Testnet::new(3); + let mut server = Homeserver::start_test(&testnet).await?; + + let public_key = Keypair::random().public_key(); + + let data = &[1, 2, 3, 4, 5]; + + server + .database_mut() + .write_entry(&public_key, "pub/foo")? + .update(data)? + .commit()?; + + let client = reqwest::Client::builder().build()?; + + let url = format!("http://localhost:{}/{public_key}/pub/foo", server.port()); + + let response = client.request(Method::GET, &url).send().await?; + + let response = client + .request(Method::GET, &url) + .header( + header::IF_NONE_MATCH, + response.headers().get(header::ETAG).unwrap(), + ) + .send() + .await?; + + assert_eq!(response.status(), StatusCode::NOT_MODIFIED); + + let response = client + .request(Method::HEAD, &url) + .header( + header::IF_NONE_MATCH, + response.headers().get(header::ETAG).unwrap(), + ) + .send() + .await?; + + assert_eq!(response.status(), StatusCode::NOT_MODIFIED); + + Ok(()) + } } From 918cea1200efb36f2e74eed3ebcd32294286f979 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 08:54:44 +0300 Subject: [PATCH 34/53] docs: add pubky icon to the readme --- .img/pubky-logo.svg | 4 ++++ README.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .img/pubky-logo.svg diff --git a/.img/pubky-logo.svg b/.img/pubky-logo.svg new file mode 100644 index 0000000..15e92ea --- /dev/null +++ b/.img/pubky-logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/README.md b/README.md index 23197ae..9d7637d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Pubky +

pubky

> The Web, long centralized, must decentralize; Long decentralized, must centralize. From 0b6c0b88e8b15659a9b0afa556258c66dc5dc18a Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 09:03:37 +0300 Subject: [PATCH 35/53] docs: update pubky logo --- .img/pubky-logo.svg | 4 ---- .svg/pubky-core-logo.svg | 4 ++++ README.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 .img/pubky-logo.svg create mode 100644 .svg/pubky-core-logo.svg diff --git a/.img/pubky-logo.svg b/.img/pubky-logo.svg deleted file mode 100644 index 15e92ea..0000000 --- a/.img/pubky-logo.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/.svg/pubky-core-logo.svg b/.svg/pubky-core-logo.svg new file mode 100644 index 0000000..6dc82d8 --- /dev/null +++ b/.svg/pubky-core-logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/README.md b/README.md index 9d7637d..f097cb3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

pubky

+

pubky

> The Web, long centralized, must decentralize; Long decentralized, must centralize. From 3bb45a5fc93c179f8a136a748e4e548a27d2f420 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 09:49:57 +0300 Subject: [PATCH 36/53] docs: update README.md with overview and features --- README.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f097cb3..4b1448c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,39 @@ -

pubky

+

pubky

+ +

+ An open protocol for per-public-key backends for censorship resistant web applications. +

+ + + > The Web, long centralized, must decentralize; Long decentralized, must centralize. +## Overview + +Pubky-core combines a [censorship resistant public-key based alternative to DNS](https://pkarr.org) with conventional, tried and tested web technologies, to keep users in control of their identities and data, while enabling developers to build software with as much availability as web apps, without the costs of managing a central database. + +## Features +- Public key based authentication. +- Public key based 3rd party authorization. +- Key-value store through PUT/GET/DELET HTTP API + pagination. + +## Getting started + > [!WARNING] > Pubky is still under heavy development and should be considered an alpha software. -> > Features might be added, removed, or changed. Data might be lost. From 1f1bbceeef2174964b77b7b57f7641a9c001a800 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 10:20:25 +0300 Subject: [PATCH 37/53] docs: update Getting started section in README.md --- README.md | 27 +++++++++++++++++++++++---- pubky-homeserver/README.md | 2 ++ pubky/README.md | 4 ++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 pubky/README.md diff --git a/README.md b/README.md index 4b1448c..ca55a27 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +

pubky

@@ -20,7 +21,6 @@

- > The Web, long centralized, must decentralize; Long decentralized, must centralize. ## Overview @@ -34,6 +34,25 @@ Pubky-core combines a [censorship resistant public-key based alternative to DNS] ## Getting started -> [!WARNING] -> Pubky is still under heavy development and should be considered an alpha software. -> Features might be added, removed, or changed. Data might be lost. +This repository contains a [Homeserver](./pubky-homeserver), and a [Client](./pubky) (both Rust and JS wasm bindings). +You can a run a local homeserver using `cargo run` with more instructions in the README. +Check the [Examples](./examples) directory for small feature-focesed examples of how to use the Pubky client. + +### JavaScript +If you prefer to use JavaScript in NodeJs/Browser or any runtime with Wasm support, you can either install from npm [`@synonymdev/pubky`](https://www.npmjs.com/package/@synonymdev/pubky) +or build the bindings yourself: +```bash +cd pubky/pkg +npm i +npm run build +``` + +#### Testing +There are unit tests for the JavaScript bindings in both NodeJs and headless web browser, but first you need to run a local temporary Homeserver +```bash +npm run testnet +``` +Then in a different terminal window: +```bash +npm test +``` diff --git a/pubky-homeserver/README.md b/pubky-homeserver/README.md index 7b884d5..f222f7e 100644 --- a/pubky-homeserver/README.md +++ b/pubky-homeserver/README.md @@ -1,5 +1,7 @@ # Pubky Homeserver +A pubky-core homeserver that acts as users' agent on the Internet, providing data availability and more.more.more.more. + ## Usage Use `cargo run` diff --git a/pubky/README.md b/pubky/README.md new file mode 100644 index 0000000..087ffc2 --- /dev/null +++ b/pubky/README.md @@ -0,0 +1,4 @@ +# Pubky + +Rust implementation implementation of [Pubky](https://github.com/pubky/pubky-core) client. + From d864572e2bd6c9026cdd531b8d3fe7d94af9eccb Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 10:23:25 +0300 Subject: [PATCH 38/53] docs: add link to js bindings in README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ca55a27..26a0daf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -

pubky

@@ -18,6 +17,10 @@ Releases + | + + JS bindings +

From 2434834618104380b935a34d72b21556073995ac Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 11:02:04 +0300 Subject: [PATCH 39/53] chore: prepare for release --- examples/Cargo.toml | 2 +- pubky-common/src/capabilities.rs | 2 +- .../src/database/tables/entries.rs | 2 +- pubky/Cargo.toml | 2 +- pubky/README.md | 49 +++++++++++++++++++ pubky/pkg/README.md | 2 +- pubky/src/error.rs | 2 +- pubky/src/lib.rs | 4 ++ pubky/src/native.rs | 4 +- pubky/src/shared/auth.rs | 15 +----- pubky/src/shared/list_builder.rs | 1 + 11 files changed, 63 insertions(+), 22 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index ca8c035..02edbbe 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -19,7 +19,7 @@ path = "./request/main.rs" anyhow = "1.0.86" base64 = "0.22.1" clap = { version = "4.5.16", features = ["derive"] } -pubky = { version = "0.1.0", path = "../pubky" } +pubky = { path = "../pubky" } pubky-common = { version = "0.1.0", path = "../pubky-common" } reqwest = "0.12.8" rpassword = "7.3.1" diff --git a/pubky-common/src/capabilities.rs b/pubky-common/src/capabilities.rs index 7929860..83848b9 100644 --- a/pubky-common/src/capabilities.rs +++ b/pubky-common/src/capabilities.rs @@ -9,7 +9,7 @@ pub struct Capability { } impl Capability { - /// Create a root [Capability] at the `/` path with all the available [PubkyAbility] + /// Create a root [Capability] at the `/` path with all the available [Action]s pub fn root() -> Self { Capability { scope: "/".to_string(), diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index 9928c34..0079a4f 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -261,7 +261,7 @@ impl Entry { // === Setters === pub fn set_timestamp(&mut self, timestamp: &Timestamp) -> &mut Self { - self.timestamp = timestamp.clone(); + self.timestamp = *timestamp; self } diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index 6871377..cc0004c 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -2,7 +2,7 @@ name = "pubky" version = "0.1.0" edition = "2021" -description = "Pubky client" +description = "Pubky core client" license = "MIT" repository = "https://github.com/pubky/pubky" keywords = ["web", "dht", "dns", "decentralized", "identity"] diff --git a/pubky/README.md b/pubky/README.md index 087ffc2..d300281 100644 --- a/pubky/README.md +++ b/pubky/README.md @@ -2,3 +2,52 @@ Rust implementation implementation of [Pubky](https://github.com/pubky/pubky-core) client. +## Quick Start + +```rust +use pkarr::mainline::Testnet; +use pkarr::Keypair; +use pubky_homeserver::Homeserver; +use pubky::PubkyClient; + +#[tokio::main] +async fn main () { + // Mainline Dht testnet and a temporary homeserver for unit testing. + let testnet = Testnet::new(10); + let server = Homeserver::start_test(&testnet).await.unwrap(); + + let client = PubkyClient::test(&testnet); + + // Uncomment the following line instead if you are not just testing. + // let client PubkyClient::builder().build(); + + // Generate a keypair + let keypair = Keypair::random(); + + // Signup to a Homeserver + let keypair = Keypair::random(); + client.signup(&keypair, &server.public_key()).await.unwrap(); + + // Write data. + let url = format!("pubky://{}/pub/foo.txt", keypair.public_key()); + let url = url.as_str(); + + client.put(url, &[0, 1, 2, 3, 4]).await.unwrap(); + + // Read using a Public key based link + let response = client.get(url).await.unwrap().unwrap(); + + assert_eq!(response, bytes::Bytes::from(vec![0, 1, 2, 3, 4])); + + // Delet an entry. + client.delete(url).await.unwrap(); + + let response = client.get(url).await.unwrap(); + + assert_eq!(response, None); +} +``` + +## Example code + +Check more [examples](https://github.com/pubky/pubky-core/tree/main/examples) for using the Pubky client. diff --git a/pubky/pkg/README.md b/pubky/pkg/README.md index 81b2cf4..4704fff 100644 --- a/pubky/pkg/README.md +++ b/pubky/pkg/README.md @@ -1,6 +1,6 @@ # Pubky -JavaScript implementation of [Pubky](https://github.com/pubky/pubky). +JavaScript implementation of [Pubky](https://github.com/pubky/pubky-core) client. ## Table of Contents - [Install](#install) diff --git a/pubky/src/error.rs b/pubky/src/error.rs index c8d80e1..b1d9a19 100644 --- a/pubky/src/error.rs +++ b/pubky/src/error.rs @@ -6,7 +6,7 @@ use pkarr::dns::SimpleDnsError; pub type Result = core::result::Result; #[derive(thiserror::Error, Debug)] -/// Pk common Error +/// Pubky crate's common Error enum pub enum Error { /// For starter, to remove as code matures. #[error("Generic error: {0}")] diff --git a/pubky/src/lib.rs b/pubky/src/lib.rs index 2b6cf42..f203d44 100644 --- a/pubky/src/lib.rs +++ b/pubky/src/lib.rs @@ -1,3 +1,6 @@ +#![doc = include_str!("../README.md")] +//! + mod error; mod shared; @@ -22,6 +25,7 @@ pub use error::Error; #[cfg(not(target_arch = "wasm32"))] pub use crate::shared::list_builder::ListBuilder; +/// A client for Pubky homeserver API, as well as generic HTTP requests to Pubky urls. #[derive(Debug, Clone)] #[wasm_bindgen] pub struct PubkyClient { diff --git a/pubky/src/native.rs b/pubky/src/native.rs index 2b04804..4a12710 100644 --- a/pubky/src/native.rs +++ b/pubky/src/native.rs @@ -101,7 +101,7 @@ impl PubkyClient { /// - DHT bootstrap nodes set to the `testnet` bootstrap nodes. /// - DHT request timout set to 500 milliseconds. (unless in CI, then it is left as default 2000) /// - /// For more control, you can use [PubkyClientBuilder::testnet] + /// For more control, you can use [PubkyClient::builder] testnet option. pub fn test(testnet: &Testnet) -> PubkyClient { let mut builder = PubkyClient::builder().testnet(testnet); @@ -184,7 +184,7 @@ impl PubkyClient { Ok(decrypt_recovery_file(recovery_file, passphrase)?) } - /// Return `pubkyauth://` url and wait for the incoming [AuthToken] + /// Return `pubkyauth://` url and wait for the incoming [pubky_common::auth::AuthToken] /// verifying that AuthToken, and if capabilities were requested, signing in to /// the Pubky's homeserver and returning the [Session] information. pub fn auth_request( diff --git a/pubky/src/shared/auth.rs b/pubky/src/shared/auth.rs index aa8cfa9..0dff599 100644 --- a/pubky/src/shared/auth.rs +++ b/pubky/src/shared/auth.rs @@ -151,20 +151,7 @@ impl PubkyClient { Ok(()) } - pub async fn inner_third_party_signin( - &self, - encrypted_token: &[u8], - client_secret: &[u8; 32], - ) -> Result { - let decrypted = decrypt(encrypted_token, client_secret)?; - let token = AuthToken::deserialize(&decrypted)?; - - self.signin_with_authtoken(&token).await?; - - Ok(token.pubky().to_owned()) - } - - pub async fn signin_with_authtoken(&self, token: &AuthToken) -> Result { + pub(crate) async fn signin_with_authtoken(&self, token: &AuthToken) -> Result { let mut url = Url::parse(&format!("https://{}/session", token.pubky()))?; self.resolve_url(&mut url).await?; diff --git a/pubky/src/shared/list_builder.rs b/pubky/src/shared/list_builder.rs index 0eaec77..32e787f 100644 --- a/pubky/src/shared/list_builder.rs +++ b/pubky/src/shared/list_builder.rs @@ -3,6 +3,7 @@ use url::Url; use crate::{error::Result, PubkyClient}; +/// Helper struct to edit Pubky homeserver's list API options before sending them. #[derive(Debug)] pub struct ListBuilder<'a> { url: Url, From fa0babc36d2a6fd77464baf75a0db35f2f29a2fa Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 11:03:11 +0300 Subject: [PATCH 40/53] chore: Release --- Cargo.lock | 2 +- pubky/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 746cb90..184a547 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1667,7 +1667,7 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "pubky" -version = "0.1.0" +version = "0.2.0" dependencies = [ "base64 0.22.1", "bytes", diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index cc0004c..c8ccc0c 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pubky" -version = "0.1.0" +version = "0.2.0" edition = "2021" description = "Pubky core client" license = "MIT" @@ -18,7 +18,7 @@ bytes = "^1.7.1" base64 = "0.22.1" pubky-common = { version = "0.1.0", path = "../pubky-common" } -pkarr = { workspace = true, features = ["async"] } +pkarr = { git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["async", "serde"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] reqwest = { version = "0.12.5", features = ["cookies", "rustls-tls"], default-features = false } From 285dd4e2d1638f332c401f5e91ae70f86c7ffac9 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 11:04:09 +0300 Subject: [PATCH 41/53] chore: Release --- Cargo.lock | 2 +- Cargo.toml | 2 +- pubky/Cargo.toml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 184a547..746cb90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1667,7 +1667,7 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "pubky" -version = "0.2.0" +version = "0.1.0" dependencies = [ "base64 0.22.1", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 1e59b0f..3b7e4d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ resolver = "2" [workspace.dependencies] -pkarr = { git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["async", "serde"] } +pkarr = { version = "2.0.0", git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["async", "serde"] } serde = { version = "^1.0.209", features = ["derive"] } [profile.release] diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index c8ccc0c..cc0004c 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pubky" -version = "0.2.0" +version = "0.1.0" edition = "2021" description = "Pubky core client" license = "MIT" @@ -18,7 +18,7 @@ bytes = "^1.7.1" base64 = "0.22.1" pubky-common = { version = "0.1.0", path = "../pubky-common" } -pkarr = { git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["async", "serde"] } +pkarr = { workspace = true, features = ["async"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] reqwest = { version = "0.12.5", features = ["cookies", "rustls-tls"], default-features = false } From a6f7acdc63a052198bfe5d92e2508c417604dbfa Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 11:05:27 +0300 Subject: [PATCH 42/53] chore: Release --- Cargo.lock | 26 +++++++++++++++++++++++--- pubky/Cargo.toml | 2 +- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 746cb90..40bbde5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,7 +149,7 @@ dependencies = [ "base64 0.22.1", "clap", "pubky", - "pubky-common", + "pubky-common 0.1.0", "reqwest", "rpassword", "tokio", @@ -1673,7 +1673,7 @@ dependencies = [ "bytes", "js-sys", "pkarr", - "pubky-common", + "pubky-common 0.1.0 (git+https://github.com/pubky/pubky-core)", "pubky_homeserver", "reqwest", "thiserror", @@ -1702,6 +1702,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "pubky-common" +version = "0.1.0" +source = "git+https://github.com/pubky/pubky-core#60c5cf10c13c17ff7e88c7e478011cdaaadff2f8" +dependencies = [ + "argon2", + "base32", + "blake3", + "crypto_secretbox", + "ed25519-dalek", + "js-sys", + "once_cell", + "pkarr", + "postcard", + "pubky-timestamp", + "rand", + "serde", + "thiserror", +] + [[package]] name = "pubky-timestamp" version = "0.2.0" @@ -1736,7 +1756,7 @@ dependencies = [ "libc", "pkarr", "postcard", - "pubky-common", + "pubky-common 0.1.0", "reqwest", "serde", "tokio", diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index cc0004c..6eb0be9 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -17,8 +17,8 @@ url = "2.5.2" bytes = "^1.7.1" base64 = "0.22.1" -pubky-common = { version = "0.1.0", path = "../pubky-common" } pkarr = { workspace = true, features = ["async"] } +pubky-common = { git = "https://github.com/pubky/pubky-core", version = "0.1.0" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] reqwest = { version = "0.12.5", features = ["cookies", "rustls-tls"], default-features = false } From 8e1ec6628b96b2098224772e7295fe1b76f44a31 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 11:09:07 +0300 Subject: [PATCH 43/53] chore: Release --- Cargo.lock | 2 +- pubky-common/Cargo.toml | 4 ++-- pubky/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40bbde5..df7398f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1667,7 +1667,7 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "pubky" -version = "0.1.0" +version = "0.2.0" dependencies = [ "base64 0.22.1", "bytes", diff --git a/pubky-common/Cargo.toml b/pubky-common/Cargo.toml index faf1d3d..56ba0c9 100644 --- a/pubky-common/Cargo.toml +++ b/pubky-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pubky-common" -version = "0.1.0" +version = "0.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,7 +10,7 @@ base32 = "0.5.0" blake3 = "1.5.1" ed25519-dalek = { version = "2.1.1", features = ["serde"] } once_cell = "1.19.0" -pkarr = { workspace = true } +pkarr = { version = "2.2.0", git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["serde"] } rand = "0.8.5" thiserror = "1.0.60" postcard = { version = "1.0.8", features = ["alloc"] } diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index 6eb0be9..461a1eb 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pubky" -version = "0.1.0" +version = "0.2.0" edition = "2021" description = "Pubky core client" license = "MIT" From 892c89c8b8325584057bd74a3abe6fb0f4509996 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 11:50:50 +0300 Subject: [PATCH 44/53] chore: publish pubky-common@0.1.0 --- Cargo.lock | 123 +++++++++++++++--------------------- pubky-common/Cargo.toml | 9 ++- pubky-homeserver/Cargo.toml | 4 +- pubky/Cargo.toml | 4 +- 4 files changed, 62 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df7398f..e51ae72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,9 +38,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -53,43 +53,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" [[package]] name = "argon2" @@ -149,7 +149,7 @@ dependencies = [ "base64 0.22.1", "clap", "pubky", - "pubky-common 0.1.0", + "pubky-common", "reqwest", "rpassword", "tokio", @@ -356,15 +356,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.1.30" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -434,9 +434,9 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "const-oid" @@ -707,9 +707,9 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -744,9 +744,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flume" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", @@ -1225,9 +1225,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.160" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libredox" @@ -1559,9 +1559,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -1571,8 +1571,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkarr" -version = "2.2.0" -source = "git+https://github.com/Pubky/pkarr?branch=serde#61232ffa1b81be20530dfb81fe31273e2c860977" +version = "2.2.1-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b59d10828418841f34089b861b33d966b63ffd34fe770f4bc46df2d8aba118f5" dependencies = [ "base32", "bytes", @@ -1652,9 +1653,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -1673,7 +1674,7 @@ dependencies = [ "bytes", "js-sys", "pkarr", - "pubky-common 0.1.0 (git+https://github.com/pubky/pubky-core)", + "pubky-common", "pubky_homeserver", "reqwest", "thiserror", @@ -1702,26 +1703,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "pubky-common" -version = "0.1.0" -source = "git+https://github.com/pubky/pubky-core#60c5cf10c13c17ff7e88c7e478011cdaaadff2f8" -dependencies = [ - "argon2", - "base32", - "blake3", - "crypto_secretbox", - "ed25519-dalek", - "js-sys", - "once_cell", - "pkarr", - "postcard", - "pubky-timestamp", - "rand", - "serde", - "thiserror", -] - [[package]] name = "pubky-timestamp" version = "0.2.0" @@ -1756,7 +1737,7 @@ dependencies = [ "libc", "pkarr", "postcard", - "pubky-common 0.1.0", + "pubky-common", "reqwest", "serde", "tokio", @@ -1887,9 +1868,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2162,9 +2143,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] @@ -2190,9 +2171,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", @@ -2201,9 +2182,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -2382,9 +2363,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.79" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -2451,18 +2432,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", @@ -2527,9 +2508,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", diff --git a/pubky-common/Cargo.toml b/pubky-common/Cargo.toml index 56ba0c9..8c9142f 100644 --- a/pubky-common/Cargo.toml +++ b/pubky-common/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "pubky-common" -version = "0.0.0" +version = "0.1.0" edition = "2021" +description = "Types and struct in common between Pubky client and homeserver" +license = "MIT" +repository = "https://github.com/pubky/pubky-core" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,15 +13,15 @@ base32 = "0.5.0" blake3 = "1.5.1" ed25519-dalek = { version = "2.1.1", features = ["serde"] } once_cell = "1.19.0" -pkarr = { version = "2.2.0", git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["serde"] } rand = "0.8.5" thiserror = "1.0.60" postcard = { version = "1.0.8", features = ["alloc"] } crypto_secretbox = { version = "0.1.1", features = ["std"] } argon2 = { version = "0.5.3", features = ["std"] } -serde = { workspace = true } pubky-timestamp = { version = "0.2.0", features = ["full"] } +serde = { version = "1.0.213", features = ["derive"] } +pkarr = { version = "2.2.1-alpha.2", features = ["serde"] } [target.'cfg(target_arch = "wasm32")'.dependencies] js-sys = "0.3.69" diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index 7cfaa34..100093e 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -17,10 +17,10 @@ heed = "0.20.3" hex = "0.4.3" httpdate = "1.0.3" libc = "0.2.159" -pkarr = { workspace = true } postcard = { version = "1.0.8", features = ["alloc"] } +pkarr = { version = "2.2.1-alpha.2", features = ["serde", "async"] } pubky-common = { version = "0.1.0", path = "../pubky-common" } -serde = { workspace = true } +serde = { version = "1.0.213", features = ["derive"] } tokio = { version = "1.37.0", features = ["full"] } toml = "0.8.19" tower-cookies = "0.10.0" diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index 461a1eb..94a7b21 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -17,8 +17,8 @@ url = "2.5.2" bytes = "^1.7.1" base64 = "0.22.1" -pkarr = { workspace = true, features = ["async"] } -pubky-common = { git = "https://github.com/pubky/pubky-core", version = "0.1.0" } +pkarr = { version = "2.2.1-alpha.2", features = ["serde", "async"] } +pubky-common = { version = "0.1.0", path = "../pubky-common" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] reqwest = { version = "0.12.5", features = ["cookies", "rustls-tls"], default-features = false } From aede289c2606204fe944919b5024ee8cefe32c50 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 25 Oct 2024 11:51:16 +0300 Subject: [PATCH 45/53] chore: Release --- Cargo.lock | 2 +- pubky/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e51ae72..f32cc60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1668,7 +1668,7 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "pubky" -version = "0.2.0" +version = "0.3.0" dependencies = [ "base64 0.22.1", "bytes", diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index 94a7b21..aa2c487 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pubky" -version = "0.2.0" +version = "0.3.0" edition = "2021" description = "Pubky core client" license = "MIT" From 0de69155d822dd62cf0b905409dccd5b1ed6e7e1 Mon Sep 17 00:00:00 2001 From: Melvin Carvalho Date: Fri, 25 Oct 2024 18:05:28 +0200 Subject: [PATCH 46/53] Fix typo DELET -> DELETE --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26a0daf..c4106bd 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Pubky-core combines a [censorship resistant public-key based alternative to DNS] ## Features - Public key based authentication. - Public key based 3rd party authorization. -- Key-value store through PUT/GET/DELET HTTP API + pagination. +- Key-value store through PUT/GET/DELETE HTTP API + pagination. ## Getting started From d1b221083d8796d6d9e77c46a1fa0b6e7da1d1cd Mon Sep 17 00:00:00 2001 From: SHAcollision Date: Thu, 31 Oct 2024 09:02:06 +0100 Subject: [PATCH 47/53] Bump dockerfile rust version --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1582693..62da9c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # ======================== # Build Stage # ======================== -FROM rust:1.81.0-alpine3.20 AS builder +FROM rust:1.82.0-alpine3.20 AS builder # Install build dependencies, including static OpenSSL libraries RUN apk add --no-cache \ From 8deda4e523ae3f1a52b19e6e333b6034da8923a6 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 7 Nov 2024 12:04:32 +0300 Subject: [PATCH 48/53] examples(authz): update the readme to explain using Authenticator cli --- examples/authz/README.md | 8 +++++++- examples/authz/authenticator.rs | 21 +++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/examples/authz/README.md b/examples/authz/README.md index 905bda6..86adf64 100644 --- a/examples/authz/README.md +++ b/examples/authz/README.md @@ -5,7 +5,7 @@ This example shows 3rd party authorization in Pubky. It consists of 2 parts: 1. [3rd party app](./3rd-party-app): A web component showing the how to implement a Pubky Auth widget. -2. [Authenticator CLI](./authenticator): A CLI showing the authenticator (key chain) asking user for consent and generating the AuthToken. +2. [Authenticator CLI](./authenticator.rs): A CLI showing the authenticator (key chain) asking user for consent and generating the AuthToken. ## Usage @@ -26,4 +26,10 @@ Copy the Pubky Auth URL from the frontend. Finally run the CLI to paste the Pubky Auth in. +```bash +cargo run --bin authenticator "" [Testnet] +``` + +Where the auth url should be within qutoatino marks, and the Testnet is an option you can set to true to use the local homeserver + You should see the frontend reacting by showing the success of authorization and session details. diff --git a/examples/authz/authenticator.rs b/examples/authz/authenticator.rs index 410b8f5..97999c0 100644 --- a/examples/authz/authenticator.rs +++ b/examples/authz/authenticator.rs @@ -17,6 +17,9 @@ struct Cli { /// Pubky Auth url url: Url, + + // Whether or not to use testnet Dht network (local testing) + testnet: Option, } #[tokio::main] @@ -62,14 +65,20 @@ async fn main() -> Result<()> { println!("Successfully decrypted recovery file..."); println!("PublicKey: {}", keypair.public_key()); - let client = PubkyClient::testnet(); + let client = if cli.testnet.unwrap_or_default() { + let client = PubkyClient::testnet(); + + // For the purposes of this demo, we need to make sure + // the user has an account on the local homeserver. + if client.signin(&keypair).await.is_err() { + client + .signup(&keypair, &PublicKey::try_from(HOMESERVER).unwrap()) + .await?; + }; - // For the purposes of this demo, we need to make sure - // the user has an account on the local homeserver. - if client.signin(&keypair).await.is_err() { client - .signup(&keypair, &PublicKey::try_from(HOMESERVER).unwrap()) - .await?; + } else { + PubkyClient::builder().build() }; println!("Sending AuthToken to the 3rd party app..."); From b29c384362d08520f87351100ba10cb4229c6f5c Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 13 Nov 2024 12:34:46 +0300 Subject: [PATCH 49/53] fix(homeserver): parsing testnet configuration --- pubky-homeserver/src/config.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/pubky-homeserver/src/config.rs b/pubky-homeserver/src/config.rs index 2b250e2..060fea7 100644 --- a/pubky-homeserver/src/config.rs +++ b/pubky-homeserver/src/config.rs @@ -114,6 +114,8 @@ impl Config { return Ok(Config { bootstrap: testnet_config.bootstrap, + port: testnet_config.port, + keypair: testnet_config.keypair, ..config }); } @@ -301,4 +303,35 @@ mod tests { } ) } + + #[test] + fn parse_with_testnet_flag() { + let config = Config::try_from_str( + r#" + # Secret key (in hex) to generate the Homeserver's Keypair + secret_key = "0123000000000000000000000000000000000000000000000000000000000000" + # Domain to be published in Pkarr records for this server to be accessible by. + domain = "localhost" + # Port for the Homeserver to listen on. + port = 6287 + # Storage directory Defaults to + storage = "/homeserver" + testnet = true + + bootstrap = ["foo", "bar"] + + # event stream + default_list_limit = 500 + max_list_limit = 10000 + "#, + ) + .unwrap(); + + assert_eq!(config.keypair, Keypair::from_secret_key(&[0; 32])); + assert_eq!(config.port, 15411); + assert_ne!( + config.bootstrap, + Some(vec!["foo".to_string(), "bar".to_string()]) + ); + } } From eb10086b5e60deb47e3816fe27bc21f52ae16c90 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 13 Nov 2024 15:15:27 +0300 Subject: [PATCH 50/53] examples: add testnet example --- Cargo.lock | 472 +++++++++++++++++++++++++++++------- examples/Cargo.toml | 6 + examples/testnet/README.md | 13 + examples/testnet/main.rs | 33 +++ pubky-homeserver/Cargo.toml | 2 +- pubky-homeserver/README.md | 12 + pubky/Cargo.toml | 2 +- pubky/pkg/package.json | 2 +- 8 files changed, 455 insertions(+), 87 deletions(-) create mode 100644 examples/testnet/README.md create mode 100644 examples/testnet/main.rs diff --git a/Cargo.lock b/Cargo.lock index f32cc60..0d89c98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,9 +38,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "argon2" @@ -147,9 +147,11 @@ version = "0.1.0" dependencies = [ "anyhow", "base64 0.22.1", + "bytes", "clap", "pubky", "pubky-common", + "pubky-homeserver", "reqwest", "rpassword", "tokio", @@ -362,9 +364,9 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" dependencies = [ "shlex", ] @@ -375,6 +377,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cipher" version = "0.4.4" @@ -463,12 +471,13 @@ dependencies = [ [[package]] name = "cookie_store" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" +checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" dependencies = [ "cookie", - "idna 0.5.0", + "document-features", + "idna 1.0.3", "log", "publicsuffix", "serde", @@ -496,9 +505,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -643,6 +652,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "document-features" version = "0.2.10" @@ -732,9 +752,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fiat-crypto" @@ -933,9 +953,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "headers" @@ -1134,9 +1154,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -1151,6 +1171,124 @@ dependencies = [ "tracing", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "idna" version = "0.3.0" @@ -1163,12 +1301,23 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1225,9 +1374,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libredox" @@ -1245,6 +1394,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "litrs" version = "0.4.1" @@ -1300,7 +1455,7 @@ dependencies = [ "serde_bencode", "serde_bytes", "sha1_smol", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -1589,7 +1744,7 @@ dependencies = [ "self_cell", "serde", "simple-dns", - "thiserror", + "thiserror 1.0.69", "tracing", "wasm-bindgen", "wasm-bindgen-futures", @@ -1675,9 +1830,9 @@ dependencies = [ "js-sys", "pkarr", "pubky-common", - "pubky_homeserver", + "pubky-homeserver", "reqwest", - "thiserror", + "thiserror 1.0.69", "tokio", "url", "wasm-bindgen", @@ -1700,26 +1855,11 @@ dependencies = [ "pubky-timestamp", "rand", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] -name = "pubky-timestamp" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084b6e5bfcc186781b71257d636b660f20e94bb588c3ba52393fd9faf7a7bfda" -dependencies = [ - "base32", - "document-features", - "getrandom", - "httpdate", - "js-sys", - "once_cell", - "serde", -] - -[[package]] -name = "pubky_homeserver" +name = "pubky-homeserver" version = "0.1.0" dependencies = [ "anyhow", @@ -1749,6 +1889,21 @@ dependencies = [ "url", ] +[[package]] +name = "pubky-timestamp" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084b6e5bfcc186781b71257d636b660f20e94bb588c3ba52393fd9faf7a7bfda" +dependencies = [ + "base32", + "document-features", + "getrandom", + "httpdate", + "js-sys", + "once_cell", + "serde", +] + [[package]] name = "publicsuffix" version = "2.2.3" @@ -1761,9 +1916,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "pin-project-lite", @@ -1772,34 +1927,38 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror", + "thiserror 2.0.3", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom", "rand", "ring", "rustc-hash", "rustls", + "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.3", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", @@ -1863,7 +2022,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1874,7 +2033,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -1889,9 +2048,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1912,9 +2071,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", @@ -2019,9 +2178,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags", "errno", @@ -2032,9 +2191,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.15" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ "once_cell", "ring", @@ -2058,6 +2217,9 @@ name = "rustls-pki-types" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -2121,9 +2283,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -2143,9 +2305,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -2171,9 +2333,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -2363,9 +2525,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.85" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -2396,6 +2558,17 @@ dependencies = [ "crossbeam-queue", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "system-configuration" version = "0.6.1" @@ -2419,9 +2592,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -2432,18 +2605,38 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", @@ -2491,6 +2684,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -2508,9 +2711,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -2778,15 +2981,27 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -2903,6 +3118,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.6" @@ -3121,6 +3346,42 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -3142,8 +3403,51 @@ dependencies = [ "syn", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 02edbbe..23efeaf 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -15,12 +15,18 @@ path = "./authz/authenticator.rs" name = "request" path = "./request/main.rs" +[[bin]] +name = "testnet" +path = "./testnet/main.rs" + [dependencies] anyhow = "1.0.86" base64 = "0.22.1" +bytes = "1.8.0" clap = { version = "4.5.16", features = ["derive"] } pubky = { path = "../pubky" } pubky-common = { version = "0.1.0", path = "../pubky-common" } +pubky-homeserver = { version = "0.1.0", path = "../pubky-homeserver" } reqwest = "0.12.8" rpassword = "7.3.1" tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] } diff --git a/examples/testnet/README.md b/examples/testnet/README.md new file mode 100644 index 0000000..3bc8a14 --- /dev/null +++ b/examples/testnet/README.md @@ -0,0 +1,13 @@ +# Testnet + +Example of using a testnet Homeserver. + +## Usage + +If you have a homeserver running in testnet mode, run: + +```bash +cargo run --bin testnet +``` + +If you want to run a Homeserver in testnet, check the `Testnet` section in the [Homeserver](../../pubky-homeserver/README.md). diff --git a/examples/testnet/main.rs b/examples/testnet/main.rs new file mode 100644 index 0000000..233ba4d --- /dev/null +++ b/examples/testnet/main.rs @@ -0,0 +1,33 @@ +//! Example of using a Testnet configuration in pubky Client + +use pubky::PubkyClient; +use pubky_common::crypto::{Keypair, PublicKey}; + +#[tokio::main] +async fn main() { + let server_public_key = + PublicKey::try_from("8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo").unwrap(); + + let client = PubkyClient::testnet(); + + let keypair = Keypair::random(); + + client.signup(&keypair, &server_public_key).await.unwrap(); + + let url = format!("pubky://{}/pub/foo.txt", keypair.public_key()); + let url = url.as_str(); + + client.put(url, &[0, 1, 2, 3, 4]).await.unwrap(); + + let response = client.get(url).await.unwrap().unwrap(); + + assert_eq!(response, bytes::Bytes::from(vec![0, 1, 2, 3, 4])); + + client.delete(url).await.unwrap(); + + let response = client.get(url).await.unwrap(); + + assert_eq!(response, None); + + println!("Successfully performed PUT, GET and DELETE requests to the testnet server") +} diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index 100093e..7b37a20 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pubky_homeserver" +name = "pubky-homeserver" version = "0.1.0" edition = "2021" diff --git a/pubky-homeserver/README.md b/pubky-homeserver/README.md index f222f7e..c8701f3 100644 --- a/pubky-homeserver/README.md +++ b/pubky-homeserver/README.md @@ -23,3 +23,15 @@ Run with an optional config file ```bash ../target/release/pubky_homeserver --config=./src/config.toml ``` + +## Testnet + +Testnet is a mode where the Homeserver is running locally, connected to an internal Mainline Testnet (not the public DHT), and acting as a Pkarr relay for clients in web browsers. + +You can run a homeserver in Testnet by passing an argument: + +```bash +cargo run --testnet +``` + +Or set the `testnet` field in the passed config file to true. diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index aa2c487..ca16763 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -32,7 +32,7 @@ wasm-bindgen = "0.2.92" wasm-bindgen-futures = "0.4.42" [dev-dependencies] -pubky_homeserver = { path = "../pubky-homeserver" } +pubky-homeserver = { path = "../pubky-homeserver" } tokio = "1.37.0" [features] diff --git a/pubky/pkg/package.json b/pubky/pkg/package.json index be3e6df..aa790bf 100644 --- a/pubky/pkg/package.json +++ b/pubky/pkg/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/pubky/pubky" }, "scripts": { - "testnet": "cargo run -p pubky_homeserver -- --testnet", + "testnet": "cargo run -p pubky-homeserver -- --testnet", "test": "npm run test-nodejs && npm run test-browser", "test-nodejs": "tape test/*.js -cov", "test-browser": "browserify test/*.js -p esmify | npx tape-run", From 6e21959d242f2dd9e67aa6c9fe9bf9f893083e50 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 13 Nov 2024 15:42:17 +0300 Subject: [PATCH 51/53] Revert "examples: add testnet example" This reverts commit eb10086b5e60deb47e3816fe27bc21f52ae16c90. --- Cargo.lock | 472 +++++++----------------------------- examples/Cargo.toml | 6 - examples/testnet/README.md | 13 - examples/testnet/main.rs | 33 --- pubky-homeserver/Cargo.toml | 2 +- pubky-homeserver/README.md | 12 - pubky/Cargo.toml | 2 +- pubky/pkg/package.json | 2 +- 8 files changed, 87 insertions(+), 455 deletions(-) delete mode 100644 examples/testnet/README.md delete mode 100644 examples/testnet/main.rs diff --git a/Cargo.lock b/Cargo.lock index 0d89c98..f32cc60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,9 +38,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" [[package]] name = "argon2" @@ -147,11 +147,9 @@ version = "0.1.0" dependencies = [ "anyhow", "base64 0.22.1", - "bytes", "clap", "pubky", "pubky-common", - "pubky-homeserver", "reqwest", "rpassword", "tokio", @@ -364,9 +362,9 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.2.0" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -377,12 +375,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "cipher" version = "0.4.4" @@ -471,13 +463,12 @@ dependencies = [ [[package]] name = "cookie_store" -version = "0.21.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" +checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" dependencies = [ "cookie", - "document-features", - "idna 1.0.3", + "idna 0.5.0", "log", "publicsuffix", "serde", @@ -505,9 +496,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -652,17 +643,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "document-features" version = "0.2.10" @@ -752,9 +732,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fiat-crypto" @@ -953,9 +933,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "headers" @@ -1154,9 +1134,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", @@ -1171,124 +1151,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "idna" version = "0.3.0" @@ -1301,23 +1163,12 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -1374,9 +1225,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libredox" @@ -1394,12 +1245,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "litrs" version = "0.4.1" @@ -1455,7 +1300,7 @@ dependencies = [ "serde_bencode", "serde_bytes", "sha1_smol", - "thiserror 1.0.69", + "thiserror", "tracing", ] @@ -1744,7 +1589,7 @@ dependencies = [ "self_cell", "serde", "simple-dns", - "thiserror 1.0.69", + "thiserror", "tracing", "wasm-bindgen", "wasm-bindgen-futures", @@ -1830,9 +1675,9 @@ dependencies = [ "js-sys", "pkarr", "pubky-common", - "pubky-homeserver", + "pubky_homeserver", "reqwest", - "thiserror 1.0.69", + "thiserror", "tokio", "url", "wasm-bindgen", @@ -1855,11 +1700,26 @@ dependencies = [ "pubky-timestamp", "rand", "serde", - "thiserror 1.0.69", + "thiserror", ] [[package]] -name = "pubky-homeserver" +name = "pubky-timestamp" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084b6e5bfcc186781b71257d636b660f20e94bb588c3ba52393fd9faf7a7bfda" +dependencies = [ + "base32", + "document-features", + "getrandom", + "httpdate", + "js-sys", + "once_cell", + "serde", +] + +[[package]] +name = "pubky_homeserver" version = "0.1.0" dependencies = [ "anyhow", @@ -1889,21 +1749,6 @@ dependencies = [ "url", ] -[[package]] -name = "pubky-timestamp" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084b6e5bfcc186781b71257d636b660f20e94bb588c3ba52393fd9faf7a7bfda" -dependencies = [ - "base32", - "document-features", - "getrandom", - "httpdate", - "js-sys", - "once_cell", - "serde", -] - [[package]] name = "publicsuffix" version = "2.2.3" @@ -1916,9 +1761,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.6" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" dependencies = [ "bytes", "pin-project-lite", @@ -1927,38 +1772,34 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.3", + "thiserror", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.9" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ "bytes", - "getrandom", "rand", "ring", "rustc-hash", "rustls", - "rustls-pki-types", "slab", - "thiserror 2.0.3", + "thiserror", "tinyvec", "tracing", - "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.7" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" dependencies = [ - "cfg_aliases", "libc", "once_cell", "socket2", @@ -2022,7 +1863,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -2033,7 +1874,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", + "regex-automata 0.4.8", "regex-syntax 0.8.5", ] @@ -2048,9 +1889,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -2071,9 +1912,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", @@ -2178,9 +2019,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags", "errno", @@ -2191,9 +2032,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "once_cell", "ring", @@ -2217,9 +2058,6 @@ name = "rustls-pki-types" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" -dependencies = [ - "web-time", -] [[package]] name = "rustls-webpki" @@ -2283,9 +2121,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -2305,9 +2143,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] @@ -2333,9 +2171,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", @@ -2525,9 +2363,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -2558,17 +2396,6 @@ dependencies = [ "crossbeam-queue", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "system-configuration" version = "0.6.1" @@ -2592,9 +2419,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.14.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -2605,38 +2432,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.69" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" -dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.69" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", @@ -2684,16 +2491,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinyvec" version = "1.8.0" @@ -2711,9 +2508,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -2981,27 +2778,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.3" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 1.0.3", + "idna 0.5.0", "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -3118,16 +2903,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webpki-roots" version = "0.26.6" @@ -3346,42 +3121,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -3403,51 +3142,8 @@ dependencies = [ "syn", ] -[[package]] -name = "zerofrom" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 23efeaf..02edbbe 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -15,18 +15,12 @@ path = "./authz/authenticator.rs" name = "request" path = "./request/main.rs" -[[bin]] -name = "testnet" -path = "./testnet/main.rs" - [dependencies] anyhow = "1.0.86" base64 = "0.22.1" -bytes = "1.8.0" clap = { version = "4.5.16", features = ["derive"] } pubky = { path = "../pubky" } pubky-common = { version = "0.1.0", path = "../pubky-common" } -pubky-homeserver = { version = "0.1.0", path = "../pubky-homeserver" } reqwest = "0.12.8" rpassword = "7.3.1" tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] } diff --git a/examples/testnet/README.md b/examples/testnet/README.md deleted file mode 100644 index 3bc8a14..0000000 --- a/examples/testnet/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Testnet - -Example of using a testnet Homeserver. - -## Usage - -If you have a homeserver running in testnet mode, run: - -```bash -cargo run --bin testnet -``` - -If you want to run a Homeserver in testnet, check the `Testnet` section in the [Homeserver](../../pubky-homeserver/README.md). diff --git a/examples/testnet/main.rs b/examples/testnet/main.rs deleted file mode 100644 index 233ba4d..0000000 --- a/examples/testnet/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Example of using a Testnet configuration in pubky Client - -use pubky::PubkyClient; -use pubky_common::crypto::{Keypair, PublicKey}; - -#[tokio::main] -async fn main() { - let server_public_key = - PublicKey::try_from("8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo").unwrap(); - - let client = PubkyClient::testnet(); - - let keypair = Keypair::random(); - - client.signup(&keypair, &server_public_key).await.unwrap(); - - let url = format!("pubky://{}/pub/foo.txt", keypair.public_key()); - let url = url.as_str(); - - client.put(url, &[0, 1, 2, 3, 4]).await.unwrap(); - - let response = client.get(url).await.unwrap().unwrap(); - - assert_eq!(response, bytes::Bytes::from(vec![0, 1, 2, 3, 4])); - - client.delete(url).await.unwrap(); - - let response = client.get(url).await.unwrap(); - - assert_eq!(response, None); - - println!("Successfully performed PUT, GET and DELETE requests to the testnet server") -} diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index 7b37a20..100093e 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pubky-homeserver" +name = "pubky_homeserver" version = "0.1.0" edition = "2021" diff --git a/pubky-homeserver/README.md b/pubky-homeserver/README.md index c8701f3..f222f7e 100644 --- a/pubky-homeserver/README.md +++ b/pubky-homeserver/README.md @@ -23,15 +23,3 @@ Run with an optional config file ```bash ../target/release/pubky_homeserver --config=./src/config.toml ``` - -## Testnet - -Testnet is a mode where the Homeserver is running locally, connected to an internal Mainline Testnet (not the public DHT), and acting as a Pkarr relay for clients in web browsers. - -You can run a homeserver in Testnet by passing an argument: - -```bash -cargo run --testnet -``` - -Or set the `testnet` field in the passed config file to true. diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index ca16763..aa2c487 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -32,7 +32,7 @@ wasm-bindgen = "0.2.92" wasm-bindgen-futures = "0.4.42" [dev-dependencies] -pubky-homeserver = { path = "../pubky-homeserver" } +pubky_homeserver = { path = "../pubky-homeserver" } tokio = "1.37.0" [features] diff --git a/pubky/pkg/package.json b/pubky/pkg/package.json index aa790bf..be3e6df 100644 --- a/pubky/pkg/package.json +++ b/pubky/pkg/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/pubky/pubky" }, "scripts": { - "testnet": "cargo run -p pubky-homeserver -- --testnet", + "testnet": "cargo run -p pubky_homeserver -- --testnet", "test": "npm run test-nodejs && npm run test-browser", "test-nodejs": "tape test/*.js -cov", "test-browser": "browserify test/*.js -p esmify | npx tape-run", From 4b1bc1c4e9aefe917602ac22b20e2f2ea3548708 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 13 Nov 2024 15:48:17 +0300 Subject: [PATCH 52/53] feat(pubky): make PubkyClient::request() public --- pubky/src/native.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pubky/src/native.rs b/pubky/src/native.rs index 4a12710..206da44 100644 --- a/pubky/src/native.rs +++ b/pubky/src/native.rs @@ -252,7 +252,8 @@ impl PubkyClient { // === HTTP === - pub(crate) fn request(&self, method: reqwest::Method, url: Url) -> RequestBuilder { + /// Make an HTTP(s) request to a URL with a Pkarr TLD + pub fn request(&self, method: reqwest::Method, url: Url) -> RequestBuilder { self.http.request(method, url) } From 0d8030f7f96e25139c7808192c30dfdb03936901 Mon Sep 17 00:00:00 2001 From: nazeh Date: Wed, 13 Nov 2024 15:50:53 +0300 Subject: [PATCH 53/53] feat(homeserver): rename pubky_homeserver to pubky-homeserver --- Cargo.lock | 34 +++++++++++++++++----------------- pubky-homeserver/Cargo.toml | 2 +- pubky/Cargo.toml | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f32cc60..0be02ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1675,7 +1675,7 @@ dependencies = [ "js-sys", "pkarr", "pubky-common", - "pubky_homeserver", + "pubky-homeserver", "reqwest", "thiserror", "tokio", @@ -1704,22 +1704,7 @@ dependencies = [ ] [[package]] -name = "pubky-timestamp" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084b6e5bfcc186781b71257d636b660f20e94bb588c3ba52393fd9faf7a7bfda" -dependencies = [ - "base32", - "document-features", - "getrandom", - "httpdate", - "js-sys", - "once_cell", - "serde", -] - -[[package]] -name = "pubky_homeserver" +name = "pubky-homeserver" version = "0.1.0" dependencies = [ "anyhow", @@ -1749,6 +1734,21 @@ dependencies = [ "url", ] +[[package]] +name = "pubky-timestamp" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084b6e5bfcc186781b71257d636b660f20e94bb588c3ba52393fd9faf7a7bfda" +dependencies = [ + "base32", + "document-features", + "getrandom", + "httpdate", + "js-sys", + "once_cell", + "serde", +] + [[package]] name = "publicsuffix" version = "2.2.3" diff --git a/pubky-homeserver/Cargo.toml b/pubky-homeserver/Cargo.toml index 100093e..7b37a20 100644 --- a/pubky-homeserver/Cargo.toml +++ b/pubky-homeserver/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pubky_homeserver" +name = "pubky-homeserver" version = "0.1.0" edition = "2021" diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index aa2c487..ca16763 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -32,7 +32,7 @@ wasm-bindgen = "0.2.92" wasm-bindgen-futures = "0.4.42" [dev-dependencies] -pubky_homeserver = { path = "../pubky-homeserver" } +pubky-homeserver = { path = "../pubky-homeserver" } tokio = "1.37.0" [features]