mirror of https://codeberg.org/pzp/pzp-invite.git
createForFriend() and createForMyself()
This commit is contained in:
parent
1b5b35bb14
commit
7283a1e5b7
232
lib/index.js
232
lib/index.js
|
@ -9,21 +9,49 @@ const p = require('promisify-tuple')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* type: 'follow' | 'join',
|
* type: 'join',
|
||||||
* hubs: number,
|
* address: string,
|
||||||
* id?: string,
|
* }} JoinCommand
|
||||||
* _hubMsAddr?: string,
|
*
|
||||||
* }} CreateOpts
|
* @typedef {`join/${string}/${string}/${string}/${string}`} JoinCommandStr
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* type: 'follow',
|
||||||
|
* id: string,
|
||||||
|
* }} FollowCommand
|
||||||
|
*
|
||||||
|
* @typedef {`follow/${string}`} FollowCommandStr
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* type: 'tunnel-connect',
|
||||||
|
* hubPubkey: string,
|
||||||
|
* targetPubkey: string,
|
||||||
|
* }} TunnelConnectCommand
|
||||||
|
*
|
||||||
|
* @typedef {`tunnel-connect/${string}/${string}`} TunnelConnectCommandStr
|
||||||
*
|
*
|
||||||
* @typedef {{type: 'join', address: string}} JoinCommand
|
|
||||||
* @typedef {{type: 'follow', id: string}} FollowCommand
|
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* type: 'promise.follow',
|
* type: 'promise.follow',
|
||||||
* issuer: string,
|
* issuerID: string,
|
||||||
* issuerType: 'pubkey' | 'identity',
|
* token: string,
|
||||||
* token: string
|
|
||||||
* }} PromiseFollowCommand
|
* }} PromiseFollowCommand
|
||||||
* @typedef {JoinCommand | FollowCommand | PromiseFollowCommand} Command
|
*
|
||||||
|
* @typedef {`promise.follow/identity.${string}/${string}`} PromiseFollowCommandStr
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* type: 'promise.identity-add',
|
||||||
|
* issuerID: string,
|
||||||
|
* token: string,
|
||||||
|
* }} PromiseIdentityAddCommand
|
||||||
|
*
|
||||||
|
* @typedef {`promise.identity-add/identity.${string}/${string}`} PromiseIdentityAddCommandStr
|
||||||
|
*
|
||||||
|
* @typedef {| JoinCommand
|
||||||
|
* | FollowCommand
|
||||||
|
* | TunnelConnectCommand
|
||||||
|
* | PromiseFollowCommand
|
||||||
|
* | PromiseIdentityAddCommand
|
||||||
|
* } Command
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +70,7 @@ function parseJoinCommand(pieces, uri) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
throw new Error(`Invalid URI "${uri}" for invite.parse, missing join hub port`)
|
throw new Error(`Invalid URI "${uri}" for invite.parse, missing join hub port`)
|
||||||
}
|
}
|
||||||
// TODO: base58 validation for the pubkey
|
// TODO: base58 validation for the pubkey (and maybe length)
|
||||||
if (!pubkey) {
|
if (!pubkey) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
throw new Error(`Invalid URI "${uri}" for invite.parse, missing join hub pubkey`)
|
throw new Error(`Invalid URI "${uri}" for invite.parse, missing join hub pubkey`)
|
||||||
|
@ -78,6 +106,29 @@ function parseFollowCommand(pieces, uri) {
|
||||||
return { type: 'follow', id }
|
return { type: 'follow', id }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<string>} pieces
|
||||||
|
* @param {string} uri
|
||||||
|
* @returns {TunnelConnectCommand}
|
||||||
|
*/
|
||||||
|
function parseTunnelConnectCommand(pieces, uri) {
|
||||||
|
const [, hubPubkey, targetPubkey] = pieces
|
||||||
|
// TODO: base58 validation for the hubPubkey (and maybe length)
|
||||||
|
if (!hubPubkey) {
|
||||||
|
// prettier-ignore
|
||||||
|
throw new Error(`Invalid URI "${uri}" for invite.parse, missing tunnel connect hubPubkey`)
|
||||||
|
}
|
||||||
|
// TODO: base58 validation for the targetPubkey (and maybe length)
|
||||||
|
if (!targetPubkey) {
|
||||||
|
// prettier-ignore
|
||||||
|
throw new Error(`Invalid URI "${uri}" for invite.parse, missing tunnel connect targetPubkey`)
|
||||||
|
}
|
||||||
|
pieces.shift()
|
||||||
|
pieces.shift()
|
||||||
|
pieces.shift()
|
||||||
|
return { type: 'tunnel-connect', hubPubkey, targetPubkey }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<string>} pieces
|
* @param {Array<string>} pieces
|
||||||
* @param {string} uri
|
* @param {string} uri
|
||||||
|
@ -96,12 +147,38 @@ function parsePromiseFollowCommand(pieces, uri) {
|
||||||
pieces.shift()
|
pieces.shift()
|
||||||
pieces.shift()
|
pieces.shift()
|
||||||
pieces.shift()
|
pieces.shift()
|
||||||
const [issuerType, issuer] = issuerAndType.split('.')
|
const [issuerType, issuerID] = issuerAndType.split('.')
|
||||||
if (issuerType !== 'pubkey' && issuerType !== 'identity') {
|
if (issuerType !== 'identity') {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
throw new Error(`Invalid URI "${uri}" for invite.parse, invalid promise.follow issuer type "${issuerType}"`)
|
throw new Error(`Invalid URI "${uri}" for invite.parse, invalid promise.follow issuer type "${issuerType}"`)
|
||||||
}
|
}
|
||||||
return { type: 'promise.follow', issuer, issuerType, token }
|
return { type: 'promise.follow', issuerID, token }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<string>} pieces
|
||||||
|
* @param {string} uri
|
||||||
|
* @returns {PromiseIdentityAddCommand}
|
||||||
|
*/
|
||||||
|
function parsePromiseIdentityAddCommand(pieces, uri) {
|
||||||
|
const [, issuerAndType, token] = pieces
|
||||||
|
if (!issuerAndType) {
|
||||||
|
// prettier-ignore
|
||||||
|
throw new Error(`Invalid URI "${uri}" for invite.parse, missing promise.identity-add issuer`)
|
||||||
|
}
|
||||||
|
if (!token) {
|
||||||
|
// prettier-ignore
|
||||||
|
throw new Error(`Invalid URI "${uri}" for invite.parse, missing promise.identity-add token`)
|
||||||
|
}
|
||||||
|
pieces.shift()
|
||||||
|
pieces.shift()
|
||||||
|
pieces.shift()
|
||||||
|
const [issuerType, issuerID] = issuerAndType.split('.')
|
||||||
|
if (issuerType !== 'identity') {
|
||||||
|
// prettier-ignore
|
||||||
|
throw new Error(`Invalid URI "${uri}" for invite.parse, invalid promise.identity-add issuer type "${issuerType}"`)
|
||||||
|
}
|
||||||
|
return { type: 'promise.identity-add', issuerID, token }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,20 +203,24 @@ function parse(uri) {
|
||||||
|
|
||||||
const commands = []
|
const commands = []
|
||||||
while (pieces.length > 0) {
|
while (pieces.length > 0) {
|
||||||
switch (pieces[0]) {
|
switch (/** @type {Command['type']} */ (pieces[0])) {
|
||||||
case 'join':
|
case 'join':
|
||||||
commands.push(parseJoinCommand(pieces, uri))
|
commands.push(parseJoinCommand(pieces, uri))
|
||||||
break
|
break
|
||||||
case 'follow':
|
case 'follow':
|
||||||
commands.push(parseFollowCommand(pieces, uri))
|
commands.push(parseFollowCommand(pieces, uri))
|
||||||
break
|
break
|
||||||
|
case 'tunnel-connect':
|
||||||
|
commands.push(parseTunnelConnectCommand(pieces, uri))
|
||||||
|
break
|
||||||
case 'promise.follow':
|
case 'promise.follow':
|
||||||
commands.push(parsePromiseFollowCommand(pieces, uri))
|
commands.push(parsePromiseFollowCommand(pieces, uri))
|
||||||
break
|
break
|
||||||
default:
|
case 'promise.identity-add':
|
||||||
console.log('Unknown command', pieces[0])
|
commands.push(parsePromiseIdentityAddCommand(pieces, uri))
|
||||||
pieces.shift()
|
|
||||||
break
|
break
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown command: "${pieces[0]}"`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,61 +230,62 @@ function parse(uri) {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'invite',
|
name: 'invite',
|
||||||
manifest: {
|
manifest: {
|
||||||
create: 'async',
|
createForFriend: 'async',
|
||||||
|
createForMyself: 'async',
|
||||||
parse: 'sync',
|
parse: 'sync',
|
||||||
},
|
},
|
||||||
|
|
||||||
parse,
|
parse,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any} sstack
|
* @param {any} local
|
||||||
* @param {any} config
|
* @param {any} config
|
||||||
*/
|
*/
|
||||||
init(sstack, config) {
|
init(local, config) {
|
||||||
if (!sstack.promise?.create) {
|
if (!local.promise?.create) {
|
||||||
throw new Error('ppppp-invite plugin requires ppppp-promise plugin')
|
throw new Error('ppppp-invite plugin requires ppppp-promise plugin')
|
||||||
}
|
}
|
||||||
if (!sstack.conn?.connect) {
|
if (!local.conn?.connect) {
|
||||||
throw new Error('ppppp-invite plugin requires ssb-conn plugin')
|
throw new Error('ppppp-invite plugin requires ssb-conn plugin')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {CreateOpts} opts
|
* @param {{
|
||||||
|
* hubs?: number,
|
||||||
|
* id: string,
|
||||||
|
* _hubMsAddr?: string,
|
||||||
|
* }} opts
|
||||||
|
*
|
||||||
* @param {CB<{uri: string, url: string}>} cb
|
* @param {CB<{uri: string, url: string}>} cb
|
||||||
*/
|
*/
|
||||||
async function create(opts, cb) {
|
async function createForFriend(opts, cb) {
|
||||||
if (typeof opts !== 'object') {
|
if (typeof opts !== 'object') {
|
||||||
return cb(new Error('invite.create is missing opts argument'))
|
return cb(new Error('invite.createForFriend is missing opts argument'))
|
||||||
}
|
}
|
||||||
const type = opts.type ?? 'follow'
|
if (!opts.id) {
|
||||||
if (type !== 'follow' && type !== 'join') {
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return cb(new Error(`invite.create opts.type should be "follow" or "join" but was "${type}"`))
|
return cb(new Error(`invite.createForFriend opts.id is required for type "follow"`))
|
||||||
}
|
|
||||||
if (type === 'follow' && !opts.id) {
|
|
||||||
// prettier-ignore
|
|
||||||
return cb(new Error(`invite.create opts.id is required for type "follow"`))
|
|
||||||
}
|
}
|
||||||
const hubs = opts.hubs ?? 1
|
const hubs = opts.hubs ?? 1
|
||||||
if (typeof hubs !== 'number') {
|
if (typeof hubs !== 'number') {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return cb(new Error(`invite.create opts.hubs should be a number but was ${hubs}`))
|
return cb(new Error(`invite.createForFriend opts.hubs should be a number but was ${hubs}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts._hubMsAddr) {
|
if (!opts._hubMsAddr) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return cb(new Error(`invite.create expected opts._hubMsAddr because loading from connDB not yet supported`))
|
return cb(new Error(`invite.createForFriend expected opts._hubMsAddr because loading from connDB not yet supported`))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to hub and create token
|
// Connect to hub and create token
|
||||||
const [err, rpc] = await p(sstack.conn.connect)(opts._hubMsAddr);
|
const [err, rpc] = await p(local.conn.connect)(opts._hubMsAddr)
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
const [err2, hubToken] = await p(rpc.hub.createToken)()
|
const [err2, hubToken] = await p(rpc.hub.createToken)()
|
||||||
if (err2) return cb(err2)
|
if (err2) return cb(err2)
|
||||||
|
|
||||||
// Parse multiserver address
|
// Parse multiserver address
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ERROR_MSG = `Invalid multiserver address ${opts._hubMsAddr} for invite.create`
|
const ERROR_MSG = `Invalid multiserver address ${opts._hubMsAddr} for invite.createForFriend`
|
||||||
const msAddr = MultiserverAddress.decode(opts._hubMsAddr)
|
const msAddr = MultiserverAddress.decode(opts._hubMsAddr)
|
||||||
const [netShsAddr, wsShsAddr] = msAddr
|
const [netShsAddr, wsShsAddr] = msAddr
|
||||||
if (!netShsAddr) return cb(new Error(ERROR_MSG))
|
if (!netShsAddr) return cb(new Error(ERROR_MSG))
|
||||||
|
@ -216,17 +298,85 @@ module.exports = {
|
||||||
const [pubkey] = shse.data
|
const [pubkey] = shse.data
|
||||||
|
|
||||||
// Create follow promise
|
// Create follow promise
|
||||||
const [err3, token] = await p(sstack.promise.create)({type: 'follow'})
|
const [err3, token] = await p(local.promise.create)({ type: 'follow' })
|
||||||
if (err3) return cb(err3)
|
if (err3) return cb(err3)
|
||||||
|
|
||||||
|
/** @type {JoinCommandStr} */
|
||||||
const joinCommand = `join/${host}/${port}/${pubkey}/${hubToken}`
|
const joinCommand = `join/${host}/${port}/${pubkey}/${hubToken}`
|
||||||
|
/** @type {FollowCommandStr} */
|
||||||
const followCommand = `follow/${opts.id}`
|
const followCommand = `follow/${opts.id}`
|
||||||
|
/** @type {PromiseFollowCommandStr} */
|
||||||
const promiseCommand = `promise.follow/identity.${opts.id}/${token}`
|
const promiseCommand = `promise.follow/identity.${opts.id}/${token}`
|
||||||
|
|
||||||
const uri = `ppppp://invite/${joinCommand}/${followCommand}/${promiseCommand}`
|
const uri = `ppppp://invite/${joinCommand}/${followCommand}/${promiseCommand}`
|
||||||
const url = `http://${host}/invite#${encodeURIComponent(uri)}`
|
const url = `http://${host}/invite#${encodeURIComponent(uri)}`
|
||||||
cb(null, {uri, url})
|
cb(null, { uri, url })
|
||||||
}
|
}
|
||||||
|
|
||||||
return { create, parse }
|
/**
|
||||||
|
* @param {{
|
||||||
|
* hubs?: number,
|
||||||
|
* id: string,
|
||||||
|
* _hubMsAddr?: string,
|
||||||
|
* }} opts
|
||||||
|
*
|
||||||
|
* @param {CB<{uri: string, url: string}>} cb
|
||||||
|
*/
|
||||||
|
async function createForMyself(opts, cb) {
|
||||||
|
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(local.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 identity-add promise
|
||||||
|
const promise = { type: 'identity-add', identity: opts.id }
|
||||||
|
const [err3, token] = await p(local.promise.create)(promise)
|
||||||
|
if (err3) return cb(err3)
|
||||||
|
|
||||||
|
/** @type {JoinCommandStr} */
|
||||||
|
const joinCommand = `join/${host}/${port}/${pubkey}/${hubToken}`
|
||||||
|
/** @type {TunnelConnectCommandStr} */
|
||||||
|
const tunnelCommand = `tunnel-connect/${pubkey}/${local.shse.pubkey}`
|
||||||
|
/** @type {PromiseIdentityAddCommandStr} */
|
||||||
|
const promiseCommand = `promise.identity-add/identity.${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 }
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,12 @@
|
||||||
"husky": "^4.3.0",
|
"husky": "^4.3.0",
|
||||||
"ppppp-caps": "github:staltz/ppppp-caps",
|
"ppppp-caps": "github:staltz/ppppp-caps",
|
||||||
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
"ppppp-keypair": "github:staltz/ppppp-keypair",
|
||||||
"ppppp-promise": "file:../promise",
|
"ppppp-promise": "github:staltz/ppppp-promise",
|
||||||
"prettier": "^2.6.2",
|
"prettier": "^2.6.2",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
"rimraf": "^5.0.1",
|
"rimraf": "^5.0.1",
|
||||||
"secret-handshake-ext": "~0.0.6",
|
"secret-handshake-ext": "0.0.8",
|
||||||
"secret-stack": "^6.4.2",
|
"secret-stack": "ssbc/secret-stack#bare-mode",
|
||||||
"typescript": "^5.0.2"
|
"typescript": "^5.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -7,8 +7,8 @@ const rimraf = require('rimraf')
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
const caps = require('ppppp-caps')
|
const caps = require('ppppp-caps')
|
||||||
|
|
||||||
test('create()', async (t) => {
|
test('createForFriend()', async (t) => {
|
||||||
const path = Path.join(os.tmpdir(), 'ppppp-promise-create-0')
|
const path = Path.join(os.tmpdir(), 'ppppp-promise-createForFriend-0')
|
||||||
rimraf.sync(path)
|
rimraf.sync(path)
|
||||||
const keypair = Keypair.generate('ed25519', 'alice')
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
|
@ -56,16 +56,14 @@ test('create()', async (t) => {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const stack = require('secret-stack/lib/api')([], {})
|
const local = require('secret-stack/bare')({caps})
|
||||||
.use(require('secret-stack/lib/core'))
|
.use(require('secret-stack/plugins/net'))
|
||||||
.use(require('secret-stack/lib/plugins/net'))
|
|
||||||
.use(require('secret-handshake-ext/secret-stack'))
|
.use(require('secret-handshake-ext/secret-stack'))
|
||||||
.use(mockConn)
|
.use(mockConn)
|
||||||
.use(mockPromise)
|
.use(mockPromise)
|
||||||
.use(require('../lib'))
|
.use(require('../lib'))
|
||||||
.call(null, {
|
.call(null, {
|
||||||
path,
|
path,
|
||||||
caps,
|
|
||||||
keypair,
|
keypair,
|
||||||
connections: {
|
connections: {
|
||||||
outgoing: {
|
outgoing: {
|
||||||
|
@ -74,8 +72,7 @@ test('create()', async (t) => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const { uri, url } = await p(stack.invite.create)({
|
const { uri, url } = await p(local.invite.createForFriend)({
|
||||||
type: 'follow',
|
|
||||||
_hubMsAddr: 'net:example.com:8008~shse:HUB_PUBKEY',
|
_hubMsAddr: 'net:example.com:8008~shse:HUB_PUBKEY',
|
||||||
id: 'MOCK_ID',
|
id: 'MOCK_ID',
|
||||||
})
|
})
|
||||||
|
@ -91,5 +88,5 @@ test('create()', async (t) => {
|
||||||
assert.ok(connectCalled)
|
assert.ok(connectCalled)
|
||||||
assert.ok(createTokenCalled)
|
assert.ok(createTokenCalled)
|
||||||
assert.ok(createPromiseCalled)
|
assert.ok(createPromiseCalled)
|
||||||
await p(stack.close)()
|
await p(local.close)()
|
||||||
})
|
})
|
|
@ -0,0 +1,92 @@
|
||||||
|
const test = require('node:test')
|
||||||
|
const assert = require('node:assert')
|
||||||
|
const Path = require('node:path')
|
||||||
|
const os = require('node:os')
|
||||||
|
const p = require('node:util').promisify
|
||||||
|
const rimraf = require('rimraf')
|
||||||
|
const Keypair = require('ppppp-keypair')
|
||||||
|
const caps = require('ppppp-caps')
|
||||||
|
|
||||||
|
test('createForMyself()', async (t) => {
|
||||||
|
const path = Path.join(os.tmpdir(), 'ppppp-promise-createForMyself-0')
|
||||||
|
rimraf.sync(path)
|
||||||
|
const keypair = Keypair.generate('ed25519', 'alice')
|
||||||
|
|
||||||
|
let connectCalled = false
|
||||||
|
let createTokenCalled = false
|
||||||
|
let createPromiseCalled = false
|
||||||
|
|
||||||
|
const mockConn = {
|
||||||
|
name: 'conn',
|
||||||
|
manifest: {
|
||||||
|
connect: 'async',
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
return {
|
||||||
|
connect(address, cb) {
|
||||||
|
connectCalled = true
|
||||||
|
assert.equal(address, 'net:example.com:8008~shse:HUB_PUBKEY')
|
||||||
|
const mockRpc = {
|
||||||
|
hub: {
|
||||||
|
createToken(cb) {
|
||||||
|
createTokenCalled = true
|
||||||
|
cb(null, 'MOCK_TOKEN')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cb(null, mockRpc)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockPromise = {
|
||||||
|
name: 'promise',
|
||||||
|
manifest: {
|
||||||
|
create: 'async',
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
return {
|
||||||
|
create(opts, cb) {
|
||||||
|
createPromiseCalled = true
|
||||||
|
assert.deepEqual(opts, { type: 'identity-add', identity: 'MOCK_ID' })
|
||||||
|
cb(null, 'MOCK_PROMISE')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const local = require('secret-stack/bare')({ caps })
|
||||||
|
.use(require('secret-stack/plugins/net'))
|
||||||
|
.use(require('secret-handshake-ext/secret-stack'))
|
||||||
|
.use(mockConn)
|
||||||
|
.use(mockPromise)
|
||||||
|
.use(require('../lib'))
|
||||||
|
.call(null, {
|
||||||
|
path,
|
||||||
|
keypair,
|
||||||
|
connections: {
|
||||||
|
outgoing: {
|
||||||
|
net: [{ transform: 'shse' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { uri, url } = await p(local.invite.createForMyself)({
|
||||||
|
_hubMsAddr: 'net:example.com:8008~shse:HUB_PUBKEY',
|
||||||
|
id: 'MOCK_ID',
|
||||||
|
})
|
||||||
|
assert.equal(
|
||||||
|
uri,
|
||||||
|
`ppppp://invite/join/example.com/8008/HUB_PUBKEY/MOCK_TOKEN/tunnel-connect/HUB_PUBKEY/${local.shse.pubkey}/promise.identity-add/identity.MOCK_ID/MOCK_PROMISE`
|
||||||
|
)
|
||||||
|
assert.equal(
|
||||||
|
url,
|
||||||
|
`http://example.com/invite#ppppp%3A%2F%2Finvite%2Fjoin%2Fexample.com%2F8008%2FHUB_PUBKEY%2FMOCK_TOKEN%2Ftunnel-connect%2FHUB_PUBKEY%2F${local.shse.pubkey}%2Fpromise.identity-add%2Fidentity.MOCK_ID%2FMOCK_PROMISE`
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.ok(connectCalled)
|
||||||
|
assert.ok(createTokenCalled)
|
||||||
|
assert.ok(createPromiseCalled)
|
||||||
|
await p(local.close)()
|
||||||
|
})
|
|
@ -29,8 +29,7 @@ test('parse() good cases', (t) => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'promise.follow',
|
type: 'promise.follow',
|
||||||
issuerType: 'identity',
|
issuerID: 'ALICE',
|
||||||
issuer: 'ALICE',
|
|
||||||
token: 'ALICE_TOKEN',
|
token: 'ALICE_TOKEN',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
Loading…
Reference in New Issue