From 42156b10f58f65a012a42da11956e25e3386fd69 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 26 Jul 2024 20:10:50 +0300 Subject: [PATCH] feat(js): signup --- pubky/Cargo.toml | 2 +- pubky/pkg/package.json | 1 + pubky/pkg/test/auth.js | 45 +++++++++++++++++++++++++++++++++++++++ pubky/pkg/test/keys.js | 6 +++--- pubky/src/error.rs | 5 +++++ pubky/src/lib.rs | 5 +++-- pubky/src/wasm.rs | 4 ++-- pubky/src/wasm/client.rs | 2 +- pubky/src/wasm/keys.rs | 10 ++++----- pubky/src/wasm/pkarr.rs | 46 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 pubky/pkg/test/auth.js create mode 100644 pubky/src/wasm/pkarr.rs diff --git a/pubky/Cargo.toml b/pubky/Cargo.toml index e3f6e93..8396f3b 100644 --- a/pubky/Cargo.toml +++ b/pubky/Cargo.toml @@ -12,12 +12,12 @@ crate-type = ["cdylib", "rlib"] [dependencies] pkarr = "2.1.0" +thiserror = "1.0.62" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] pubky-common = { version = "0.1.0", path = "../pubky-common" } ureq = { version = "2.10.0", features = ["cookies"] } -thiserror = "1.0.62" url = "2.5.2" flume = { version = "0.11.0", features = ["select", "eventual-fairness"], default-features = false } bytes = "1.6.1" diff --git a/pubky/pkg/package.json b/pubky/pkg/package.json index 3c48852..b3e43e9 100644 --- a/pubky/pkg/package.json +++ b/pubky/pkg/package.json @@ -11,6 +11,7 @@ "scripts": { "lint": "standard --fix", "test": "brittle test/*.js -cov", + "preinstall": "cargo run --bin bundle_pubky_npm", "prepublishOnly": "npm run lint && npm run test" }, "files": [ diff --git a/pubky/pkg/test/auth.js b/pubky/pkg/test/auth.js new file mode 100644 index 0000000..0bc1b52 --- /dev/null +++ b/pubky/pkg/test/auth.js @@ -0,0 +1,45 @@ +import test from 'brittle' +import z32 from 'z32' + +import App from '@pubky/homeserver/test/helper/app.js' + +import Client from '../src/index.js' + +test('seed auth', async (t) => { + // const homeserver = await App(t) + + // const client = new Client( + // homeserver.homeserver.pkarr.serverPkarr.publicKey(), + // { + // relay: homeserver.testnet.relay + // } + // ) + // await client.ready() + // + // const seed = Client.crypto.generateSeed() + // const keypair = Client.crypto.generateKeyPair(seed) + // const expectedUserId = keypair.public_key().to_string() + // + // const userIdResult = await client.signup(seed) + // t.ok(userIdResult.isOk(), userIdResult.error) + // + // const userId = userIdResult.value + // t.is(userId, expectedUserId) + // + // const session = await client.session() + // t.ok(session?.users[userId]) + // + // { + // await client.logout(userId) + // + // const session = await client.session() + // t.absent(session?.users?.[userId]) + // } + // + // { + // await client.login(seed) + // + // const session = await client.session() + // t.ok(session?.users[userId]) + // } +}) diff --git a/pubky/pkg/test/keys.js b/pubky/pkg/test/keys.js index 3564964..d01467a 100644 --- a/pubky/pkg/test/keys.js +++ b/pubky/pkg/test/keys.js @@ -5,9 +5,9 @@ import { Keypair } from '../index.js' test('generate keys from a seed', async (t) => { const secretkey = Buffer.from('5aa93b299a343aa2691739771f2b5b85e740ca14c685793d67870f88fa89dc51', 'hex') - const keypair = Keypair.fromSecretKey(secretkey) + const keypair = Keypair.from_secret_key(secretkey) - const publicKey = keypair.publicKey() + const publicKey = keypair.public_key() - t.is(publicKey.toString(), 'gcumbhd7sqit6nn457jxmrwqx9pyymqwamnarekgo3xppqo6a19o') + t.is(publicKey.to_string(), 'gcumbhd7sqit6nn457jxmrwqx9pyymqwamnarekgo3xppqo6a19o') }) diff --git a/pubky/src/error.rs b/pubky/src/error.rs index acbad4b..f051d14 100644 --- a/pubky/src/error.rs +++ b/pubky/src/error.rs @@ -23,18 +23,23 @@ pub enum Error { Pkarr(#[from] pkarr::Error), #[error(transparent)] + #[cfg(not(target_arch = "wasm32"))] Flume(#[from] flume::RecvError), #[error(transparent)] + #[cfg(not(target_arch = "wasm32"))] Ureq(#[from] Box), #[error(transparent)] + #[cfg(not(target_arch = "wasm32"))] Url(#[from] url::ParseError), #[error(transparent)] + #[cfg(not(target_arch = "wasm32"))] Session(#[from] pubky_common::session::Error), } +#[cfg(not(target_arch = "wasm32"))] impl From for Error { fn from(error: ureq::Error) -> Self { Error::Ureq(Box::new(error)) diff --git a/pubky/src/lib.rs b/pubky/src/lib.rs index afa33b6..39955c4 100644 --- a/pubky/src/lib.rs +++ b/pubky/src/lib.rs @@ -14,13 +14,14 @@ macro_rules! if_wasm { )*} } +mod error; +pub use error::Error; + if_not_wasm! { mod client; mod client_async; - mod error; pub use client::PubkyClient; - pub use error::Error; } if_wasm! { diff --git a/pubky/src/wasm.rs b/pubky/src/wasm.rs index faddf5b..9610160 100644 --- a/pubky/src/wasm.rs +++ b/pubky/src/wasm.rs @@ -1,6 +1,6 @@ -mod keys; - mod client; +mod keys; +mod pkarr; pub use client::PubkyClient; pub use keys::Keypair; diff --git a/pubky/src/wasm/client.rs b/pubky/src/wasm/client.rs index 550c8e5..e692cb8 100644 --- a/pubky/src/wasm/client.rs +++ b/pubky/src/wasm/client.rs @@ -11,7 +11,7 @@ pub struct Error {} #[wasm_bindgen] pub struct PubkyClient { - pkarr: PkarrRelayClient, + pub(crate) pkarr: PkarrRelayClient, } #[wasm_bindgen] diff --git a/pubky/src/wasm/keys.rs b/pubky/src/wasm/keys.rs index 6f6c6dd..f73489d 100644 --- a/pubky/src/wasm/keys.rs +++ b/pubky/src/wasm/keys.rs @@ -13,7 +13,7 @@ impl Keypair { #[wasm_bindgen] /// Generate a [Keypair] from a secret key. - pub fn fromSecretKey(secret_key: js_sys::Uint8Array) -> Self { + pub fn from_secret_key(secret_key: js_sys::Uint8Array) -> Self { let mut bytes = [0; 32]; secret_key.copy_to(&mut bytes); @@ -22,7 +22,7 @@ impl Keypair { #[wasm_bindgen] /// Returns the [PublicKey] of this keypair. - pub fn publicKey(&self) -> PublicKey { + pub fn public_key(&self) -> PublicKey { PublicKey(self.0.public_key()) } } @@ -33,13 +33,13 @@ pub struct PublicKey(pkarr::PublicKey); #[wasm_bindgen] impl PublicKey { #[wasm_bindgen] - /// Return the public key as Uint8Array - pub fn toBytes(&self) -> js_sys::Uint8Array { + /// Convert the PublicKey to Uint8Array + pub fn to_uint8array(&self) -> js_sys::Uint8Array { js_sys::Uint8Array::from(self.0.as_bytes().as_slice()) } #[wasm_bindgen] - pub fn toString(&self) -> String { + pub fn to_string(&self) -> String { self.0.to_string() } } diff --git a/pubky/src/wasm/pkarr.rs b/pubky/src/wasm/pkarr.rs new file mode 100644 index 0000000..81a5685 --- /dev/null +++ b/pubky/src/wasm/pkarr.rs @@ -0,0 +1,46 @@ +use wasm_bindgen::prelude::*; + +pub use pkarr::{ + dns::{rdata::SVCB, Packet}, + Keypair, PublicKey, SignedPacket, +}; + +use crate::error::Result; + +use super::PubkyClient; + +// TODO: Share more code with the non-wasm client. + +impl PubkyClient { + /// Publish the SVCB record for `_pubky.`. + pub(crate) async fn publish_pubky_homeserver( + &self, + keypair: &Keypair, + host: &str, + ) -> Result<()> { + let mut packet = Packet::new_reply(0); + + if let Some(existing) = self.pkarr.resolve(&keypair.public_key()).await? { + for answer in existing.packet().answers.iter().cloned() { + if !answer.name.to_string().starts_with("_pubky") { + packet.answers.push(answer.into_owned()) + } + } + } + + let svcb = SVCB::new(0, host.try_into()?); + + packet.answers.push(pkarr::dns::ResourceRecord::new( + "_pubky".try_into().unwrap(), + pkarr::dns::CLASS::IN, + 60 * 60, + pkarr::dns::rdata::RData::SVCB(svcb), + )); + + let signed_packet = SignedPacket::from_packet(keypair, &packet)?; + + self.pkarr.publish(&signed_packet).await?; + + Ok(()) + } +}