diff --git a/pubky/pkg/package.json b/pubky/pkg/package.json index 6532b95..e633cc3 100644 --- a/pubky/pkg/package.json +++ b/pubky/pkg/package.json @@ -2,18 +2,18 @@ "name": "@synonymdev/pubky", "type": "module", "description": "Pubky client", - "version": "0.1.0", + "version": "0.0.1", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/pubky/pubky" }, "scripts": { - "lint": "standard --fix", "test": "tape test/*.js -cov", "test-browser": "browserify test/*.js -p esmify | npx tape-run", - "preinstall": "cargo run --bin bundle_pubky_npm", - "prepublishOnly": "npm run lint && npm run test" + "build": "cargo run --bin bundle_pubky_npm", + "preinstall": "npm run build", + "prepublishOnly": "npm run build && npm run test && npm run test-browser" }, "files": [ "nodejs/*", @@ -36,7 +36,6 @@ "devDependencies": { "browser-resolve": "^2.0.0", "esmify": "^2.1.1", - "standard": "^17.1.0", "tape": "^5.8.1", "tape-run": "^11.0.0" } diff --git a/pubky/src/lib.rs b/pubky/src/lib.rs index 48bcb81..72f2df5 100644 --- a/pubky/src/lib.rs +++ b/pubky/src/lib.rs @@ -8,6 +8,12 @@ mod native; #[cfg(target_arch = "wasm32")] mod wasm; +#[cfg(target_arch = "wasm32")] +use std::{ + collections::HashSet, + sync::{Arc, RwLock}, +}; + use wasm_bindgen::prelude::*; #[cfg(not(target_arch = "wasm32"))] @@ -21,4 +27,7 @@ pub struct PubkyClient { http: reqwest::Client, #[cfg(not(target_arch = "wasm32"))] pub(crate) pkarr: PkarrClientAsync, + /// A cookie jar for nodejs fetch. + #[cfg(target_arch = "wasm32")] + pub(crate) session_cookies: Arc>>, } diff --git a/pubky/src/native.rs b/pubky/src/native.rs index fa2ae3f..e6627cc 100644 --- a/pubky/src/native.rs +++ b/pubky/src/native.rs @@ -8,7 +8,7 @@ use ::pkarr::{ }; use pkarr::Keypair; use pubky_common::session::Session; -use reqwest::{Method, RequestBuilder}; +use reqwest::{Method, RequestBuilder, Response}; use url::Url; use crate::{error::Result, PubkyClient}; @@ -94,4 +94,7 @@ impl PubkyClient { pub(crate) fn request(&self, method: reqwest::Method, url: Url) -> RequestBuilder { self.http.request(method, url) } + + pub(crate) fn store_session(&self, response: Response) {} + pub(crate) fn remove_session(&self, pubky: &PublicKey) {} } diff --git a/pubky/src/shared/auth.rs b/pubky/src/shared/auth.rs index e78f84a..276ab1d 100644 --- a/pubky/src/shared/auth.rs +++ b/pubky/src/shared/auth.rs @@ -20,15 +20,19 @@ impl PubkyClient { ) -> Result<()> { let homeserver = homeserver.to_string(); + let public_key = &keypair.public_key(); + let (audience, mut url) = self.resolve_endpoint(&homeserver).await?; - url.set_path(&format!("/{}", keypair.public_key())); + url.set_path(&format!("/{}", public_key)); let body = AuthnSignature::generate(keypair, &audience) .as_bytes() .to_owned(); - self.request(Method::PUT, url).body(body).send().await?; + let response = self.request(Method::PUT, url).body(body).send().await?; + + self.store_session(response); self.publish_pubky_homeserver(keypair, &homeserver).await?; @@ -67,6 +71,8 @@ impl PubkyClient { self.request(Method::DELETE, url).send().await?; + self.remove_session(pubky); + Ok(()) } @@ -82,7 +88,9 @@ impl PubkyClient { .as_bytes() .to_owned(); - self.request(Method::POST, url).body(body).send().await?; + let response = self.request(Method::POST, url).body(body).send().await?; + + self.store_session(response); Ok(()) } diff --git a/pubky/src/wasm.rs b/pubky/src/wasm.rs index 01fcf73..e572670 100644 --- a/pubky/src/wasm.rs +++ b/pubky/src/wasm.rs @@ -1,6 +1,11 @@ +use std::{ + collections::HashSet, + sync::{Arc, RwLock}, +}; + use wasm_bindgen::prelude::*; -use reqwest::{Method, RequestBuilder}; +use reqwest::{Method, RequestBuilder, Response}; use url::Url; use crate::PubkyClient; @@ -18,6 +23,7 @@ impl PubkyClient { pub fn new() -> Self { Self { http: reqwest::Client::builder().build().unwrap(), + session_cookies: Arc::new(RwLock::new(HashSet::new())), } } @@ -60,7 +66,37 @@ impl PubkyClient { .map_err(|e| e.into()) } - pub(crate) fn request(&self, method: Method, url: Url) -> reqwest::RequestBuilder { - self.http.request(method, url).fetch_credentials_include() + pub(crate) fn request(&self, method: reqwest::Method, url: Url) -> RequestBuilder { + let request = self.http.request(method, url).fetch_credentials_include(); + + for cookie in self.session_cookies.read().unwrap().iter() { + return request.header("Cookie", cookie); + } + + request + } + + // Support cookies for nodejs + + pub(crate) fn store_session(&self, response: Response) { + if let Some(cookie) = response + .headers() + .get("set-cookie") + .and_then(|h| h.to_str().ok()) + .and_then(|s| s.split(';').next()) + { + self.session_cookies + .write() + .unwrap() + .insert(cookie.to_string()); + } + } + pub(crate) fn remove_session(&self, pubky: &pkarr::PublicKey) { + let key = pubky.to_string(); + + self.session_cookies + .write() + .unwrap() + .retain(|cookie| !cookie.starts_with(&key)); } }