OverviewFilesCommitsIssuesDocsReleasesPeers

favela-host / test / sign-in.test.js

57 lines · javascript ref:
// The desktop app boots on a node someone already signed into.
//
// ⛔ WHY. `signIn` proves THIS APP's own browser key, claiming the node on first run — on a handset the
// app IS the browser, and the worklet relies on it throwing when it cannot. But on a desktop or server
// the node has usually been claimed already, by a real browser through favela-surface. `boot()` passed
// that throw straight up, so the one-app desktop host could not start on either server (hyper-social
// #77 §5, change 2). Serving the surface does not need the app's own session: browsers sign in
// themselves. So boot signs in when it can and serves either way, saying which.

import test from 'brittle'
import fs from 'bare-fs'
import os from 'bare-os'
import { join } from 'bare-path'
import { FavelaNode } from 'favela-peer/lib/node.js'
import { dispatch } from 'favela-peer/lib/rpc.js'
import { an } from 'anproto'
import { signIn, signInOrServe } from '../lib/host.js'

const tmp = (name) => { const d = join(os.tmpdir(), 'fh-signin-' + name + '-' + Date.now() + '-' + Math.random().toString(16).slice(2)); fs.mkdirSync(d, { recursive: true }); return d }
const stub = () => ({ async join () {}, async leave () {}, async destroy () {} })

async function node (t, name) {
  const storage = tmp(name)
  const n = new FavelaNode(storage, { transport: stub() })
  await n.ready()
  t.teardown(() => n.close())
  return { n, storage }
}

// Another browser claims the node first, the way favela-surface's login page does.
async function claimByAnotherBrowser (n) {
  const kp = await an.gen()
  const { challenge } = await dispatch(n, 'browser-challenge', {})
  await dispatch(n, 'browser-claim', { publicKey: an.publicKey(kp), challenge, signature: await an.sign(await an.hash(challenge), kp) })
}

test('signIn still throws on a node another browser claimed (the handset relies on it)', async (t) => {
  const { n, storage } = await node(t, 'throws')
  await claimByAnotherBrowser(n)
  await t.exception(() => signIn(n, storage), /already claimed/)
})

test('signInOrServe: on a node another browser claimed, boot continues — no app session, and it says why', async (t) => {
  const { n, storage } = await node(t, 'serves')
  await claimByAnotherBrowser(n)
  const who = await signInOrServe(n, storage)
  t.is(who.signedIn, false)
  t.ok(/claimed/.test(who.reason), 'the reason is reported: ' + who.reason)
})

test('signInOrServe: on an unclaimed node it claims, exactly as signIn does', async (t) => {
  const { n, storage } = await node(t, 'claims')
  const who = await signInOrServe(n, storage)
  t.is(who.signedIn, true)
  t.is(who.claimed, true)
})