From 149b2dd86fe4306a6d023dda442d8a9102ee6378 Mon Sep 17 00:00:00 2001 From: Andre Staltz Date: Mon, 8 Jan 2024 11:53:32 +0200 Subject: [PATCH] update secret-stack to 8.1 --- lib/index.js | 315 ++++++++++++++++++++++----------------------------- package.json | 2 +- 2 files changed, 135 insertions(+), 182 deletions(-) diff --git a/lib/index.js b/lib/index.js index bbda417..19aa507 100644 --- a/lib/index.js +++ b/lib/index.js @@ -67,17 +67,13 @@ function parseJoinCommand(pieces, uri) { // prettier-ignore throw new Error(`Invalid URI "${uri}" for invite.parse, missing join hub pubkey`) } - // TODO: base58 validation for the token - if (!token) { - // prettier-ignore - throw new Error(`Invalid URI "${uri}" for invite.parse, missing join hub token`) - } + // TODO: base58 validation for the token, if present at all pieces.shift() pieces.shift() pieces.shift() pieces.shift() pieces.shift() - const shse = `shse:${pubkey}:${token}` + const shse = token ? `shse:${pubkey}:${token}` : `shse:${pubkey}` const address = `net:${host}:${port}~${shse}` // TODO: add ws address here return { type: 'join', address } } @@ -221,194 +217,151 @@ function parse(uri) { } /** - * @param {{ shse: SHSE | null }} peer - * @returns {asserts peer is { shse: SHSE }} + * @param {{ + * shse: SHSE; + * promise: PPPPPPromise; + * conn: ConnPlugin; + * }} peer + * @param {unknown} config */ -function assertSHSEExists(peer) { - if (!peer.shse) throw new Error('"invite" plugin requires "shse" plugin') -} +function initInvite(peer, config) { + /** + * @param {{ + * hubs?: number, + * id: string, + * _hubMsAddr?: string, + * }} opts + * + * @param {CB<{uri: string, url: string}>} cb + */ + async function createForFriend(opts, cb) { + if (typeof opts !== 'object') { + return cb(new Error('invite.createForFriend is missing opts argument')) + } + if (!opts.id) { + // prettier-ignore + return cb(new Error(`invite.createForFriend opts.id is required for type "follow"`)) + } + const hubs = opts.hubs ?? 1 + if (typeof hubs !== 'number') { + // prettier-ignore + return cb(new Error(`invite.createForFriend opts.hubs should be a number but was ${hubs}`)) + } -/** - * @param {{ promise: PPPPPPromise | null }} peer - * @returns {asserts peer is { promise: PPPPPPromise }} - */ -function assertPromisePlugin(peer) { - // prettier-ignore - if (!peer.promise) throw new Error('"invite" plugin requires "promise" plugin') -} + if (!opts._hubMsAddr) { + // prettier-ignore + return cb(new Error(`invite.createForFriend expected opts._hubMsAddr because loading from connDB not yet supported`)) + } -/** - * @param {{ conn: ConnPlugin | null }} peer - * @returns {asserts peer is { conn: ConnPlugin }} - */ -function assertConnPlugin(peer) { - if (!peer.conn) throw new Error('"invite" plugin requires "conn" plugin') -} + // Connect to hub and create token + const [err, rpc] = await p(peer.conn.connect)(opts._hubMsAddr) + if (err) return cb(err) + const [err2, hubToken] = await p(rpc.hub.createToken)() + if (err2) return cb(err2) -module.exports = { - name: 'invite', - manifest: { - createForFriend: 'async', - createForMyself: 'async', - parse: 'sync', - }, + // Parse multiserver address + // prettier-ignore + const ERROR_MSG = `Invalid multiserver address ${opts._hubMsAddr} for invite.createForFriend` + const msAddr = MultiserverAddress.decode(opts._hubMsAddr) + const [netShsAddr, wsShsAddr] = msAddr + if (!netShsAddr) return cb(new Error(ERROR_MSG)) + const [net, shse] = netShsAddr + if (!net) return cb(new Error(ERROR_MSG)) + if (net.name !== 'net') return cb(new Error(ERROR_MSG)) + const [host, port] = net.data + if (!shse) return cb(new Error(ERROR_MSG)) + if (shse.name !== 'shse') return cb(new Error(ERROR_MSG)) + const [pubkey] = shse.data - parse, + // Create follow promise + const [err3, token] = await p(peer.promise.create)({ type: 'follow' }) + if (err3) return cb(err3) + + /** @type {JoinCommandStr} */ + const joinCommand = `join/${host}/${port}/${pubkey}/${hubToken}` + /** @type {FollowCommandStr} */ + const followCommand = `follow/${opts.id}` + /** @type {PromiseFollowCommandStr} */ + const promiseCommand = `promise.follow/account.${opts.id}/${token}` + + const uri = `ppppp://invite/${joinCommand}/${followCommand}/${promiseCommand}` + const url = `http://${host}/invite#${encodeURIComponent(uri)}` + cb(null, { uri, url }) + } /** * @param {{ - * shse: SHSE | null; - * promise: PPPPPPromise | null; - * conn: ConnPlugin | null; - * }} peer - * @param {unknown} config + * hubs?: number, + * id: string, + * _hubMsAddr?: string, + * }} opts + * + * @param {CB<{uri: string, url: string}>} cb */ - init(peer, config) { - assertSHSEExists(peer) - assertPromisePlugin(peer) - assertConnPlugin(peer) - - /** - * @param {{ - * hubs?: number, - * id: string, - * _hubMsAddr?: string, - * }} opts - * - * @param {CB<{uri: string, url: string}>} cb - */ - async function createForFriend(opts, cb) { - try { - assertConnPlugin(peer) - assertPromisePlugin(peer) - } catch (err) { - return cb(/**@type {Error}*/ (err)) - } - if (typeof opts !== 'object') { - return cb(new Error('invite.createForFriend is missing opts argument')) - } - if (!opts.id) { - // prettier-ignore - return cb(new Error(`invite.createForFriend opts.id is required for type "follow"`)) - } - const hubs = opts.hubs ?? 1 - if (typeof hubs !== 'number') { - // prettier-ignore - return cb(new Error(`invite.createForFriend opts.hubs should be a number but was ${hubs}`)) - } - - if (!opts._hubMsAddr) { - // prettier-ignore - return cb(new Error(`invite.createForFriend expected opts._hubMsAddr because loading from connDB not yet supported`)) - } - - // Connect to hub and create token - const [err, rpc] = await p(peer.conn.connect)(opts._hubMsAddr) - if (err) return cb(err) - const [err2, hubToken] = await p(rpc.hub.createToken)() - if (err2) return cb(err2) - - // Parse multiserver address + async function createForMyself(opts, cb) { + if (typeof opts !== 'object') { + return cb(new Error('invite.createForMyself is missing opts argument')) + } + if (!opts.id) { // prettier-ignore - const ERROR_MSG = `Invalid multiserver address ${opts._hubMsAddr} for invite.createForFriend` - const msAddr = MultiserverAddress.decode(opts._hubMsAddr) - const [netShsAddr, wsShsAddr] = msAddr - if (!netShsAddr) return cb(new Error(ERROR_MSG)) - const [net, shse] = netShsAddr - if (!net) return cb(new Error(ERROR_MSG)) - if (net.name !== 'net') return cb(new Error(ERROR_MSG)) - const [host, port] = net.data - if (!shse) return cb(new Error(ERROR_MSG)) - if (shse.name !== 'shse') return cb(new Error(ERROR_MSG)) - const [pubkey] = shse.data - - // Create follow promise - const [err3, token] = await p(peer.promise.create)({ type: 'follow' }) - if (err3) return cb(err3) - - /** @type {JoinCommandStr} */ - const joinCommand = `join/${host}/${port}/${pubkey}/${hubToken}` - /** @type {FollowCommandStr} */ - const followCommand = `follow/${opts.id}` - /** @type {PromiseFollowCommandStr} */ - const promiseCommand = `promise.follow/account.${opts.id}/${token}` - - const uri = `ppppp://invite/${joinCommand}/${followCommand}/${promiseCommand}` - const url = `http://${host}/invite#${encodeURIComponent(uri)}` - cb(null, { uri, url }) + return cb(new Error(`invite.createForMyself opts.id is required for type "follow"`)) + } + const hubs = opts.hubs ?? 1 + if (typeof hubs !== 'number') { + // prettier-ignore + return cb(new Error(`invite.createForMyself opts.hubs should be a number but was ${hubs}`)) } - /** - * @param {{ - * hubs?: number, - * id: string, - * _hubMsAddr?: string, - * }} opts - * - * @param {CB<{uri: string, url: string}>} cb - */ - async function createForMyself(opts, cb) { - try { - assertSHSEExists(peer) - assertConnPlugin(peer) - assertPromisePlugin(peer) - } catch (err) { - return cb(/**@type {Error}*/ (err)) - } - if (typeof opts !== 'object') { - return cb(new Error('invite.createForMyself is missing opts argument')) - } - if (!opts.id) { - // prettier-ignore - return cb(new Error(`invite.createForMyself opts.id is required for type "follow"`)) - } - const hubs = opts.hubs ?? 1 - if (typeof hubs !== 'number') { - // prettier-ignore - return cb(new Error(`invite.createForMyself opts.hubs should be a number but was ${hubs}`)) - } - - if (!opts._hubMsAddr) { - // prettier-ignore - return cb(new Error(`invite.createForMyself expected opts._hubMsAddr because loading from connDB not yet supported`)) - } - - // Connect to hub and create token - const [err, rpc] = await p(peer.conn.connect)(opts._hubMsAddr) - if (err) return cb(err) - const [err2, hubToken] = await p(rpc.hub.createToken)() - if (err2) return cb(err2) - - // Parse multiserver address + if (!opts._hubMsAddr) { // prettier-ignore - const ERROR_MSG = `Invalid multiserver address ${opts._hubMsAddr} for invite.createForMyself` - const msAddr = MultiserverAddress.decode(opts._hubMsAddr) - const [netShsAddr, wsShsAddr] = msAddr - if (!netShsAddr) return cb(new Error(ERROR_MSG)) - const [net, shse] = netShsAddr - if (!net) return cb(new Error(ERROR_MSG)) - if (net.name !== 'net') return cb(new Error(ERROR_MSG)) - const [host, port] = net.data - if (!shse) return cb(new Error(ERROR_MSG)) - if (shse.name !== 'shse') return cb(new Error(ERROR_MSG)) - const [pubkey] = shse.data - - // Create account-add promise - const promise = { type: 'account-add', account: opts.id } - const [err3, token] = await p(peer.promise.create)(promise) - if (err3) return cb(err3) - - /** @type {JoinCommandStr} */ - const joinCommand = `join/${host}/${port}/${pubkey}/${hubToken}` - /** @type {TunnelConnectCommandStr} */ - const tunnelCommand = `tunnel-connect/${pubkey}/${peer.shse.pubkey}` - /** @type {PromiseAccountAddCommandStr} */ - const promiseCommand = `promise.account-add/account.${opts.id}/${token}` - const uri = `ppppp://invite/${joinCommand}/${tunnelCommand}/${promiseCommand}` - const url = `http://${host}/invite#${encodeURIComponent(uri)}` - cb(null, { uri, url }) + return cb(new Error(`invite.createForMyself expected opts._hubMsAddr because loading from connDB not yet supported`)) } - return { createForFriend, createForMyself, parse } - }, + // Connect to hub and create token + const [err, rpc] = await p(peer.conn.connect)(opts._hubMsAddr) + if (err) return cb(err) + const [err2, hubToken] = await p(rpc.hub.createToken)() + if (err2) return cb(err2) + + // Parse multiserver address + // prettier-ignore + const ERROR_MSG = `Invalid multiserver address ${opts._hubMsAddr} for invite.createForMyself` + const msAddr = MultiserverAddress.decode(opts._hubMsAddr) + const [netShsAddr, wsShsAddr] = msAddr + if (!netShsAddr) return cb(new Error(ERROR_MSG)) + const [net, shse] = netShsAddr + if (!net) return cb(new Error(ERROR_MSG)) + if (net.name !== 'net') return cb(new Error(ERROR_MSG)) + const [host, port] = net.data + if (!shse) return cb(new Error(ERROR_MSG)) + if (shse.name !== 'shse') return cb(new Error(ERROR_MSG)) + const [pubkey] = shse.data + + // Create account-add promise + const promise = { type: 'account-add', account: opts.id } + const [err3, token] = await p(peer.promise.create)(promise) + if (err3) return cb(err3) + + /** @type {JoinCommandStr} */ + const joinCommand = `join/${host}/${port}/${pubkey}/${hubToken}` + /** @type {TunnelConnectCommandStr} */ + const tunnelCommand = `tunnel-connect/${pubkey}/${peer.shse.pubkey}` + /** @type {PromiseAccountAddCommandStr} */ + const promiseCommand = `promise.account-add/account.${opts.id}/${token}` + const uri = `ppppp://invite/${joinCommand}/${tunnelCommand}/${promiseCommand}` + const url = `http://${host}/invite#${encodeURIComponent(uri)}` + cb(null, { uri, url }) + } + + return { createForFriend, createForMyself, parse } } + +exports.name = 'invite' +exports.needs = ['shse', 'promise', 'conn'] +exports.manifest = { + createForFriend: 'async', + createForMyself: 'async', + parse: 'sync', +} +exports.init = initInvite +exports.parse = parse diff --git a/package.json b/package.json index dccb37d..5e74493 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "pretty-quick": "^3.1.3", "rimraf": "^5.0.1", "secret-handshake-ext": "0.0.11", - "secret-stack": "~8.0.0", + "secret-stack": "~8.1.0", "typescript": "^5.1.3" }, "scripts": {