UNPKG

edge-core-js

Version:

Edge account & wallet management library

204 lines (171 loc) 5.12 kB
import { makeMemoryDisklet } from 'disklet' import { base16, base64 } from 'rfc4648' import { makeFetchFunction } from 'serverlet' import { bridgifyObject, close } from 'yaob' import { fixUsername } from '../../client-side' import { asEdgeLoginDump, asEdgeRepoDump, wasEdgeLoginDump, wasEdgeRepoDump } from '../../types/fake-types' import { asLoginPayload } from '../../types/server-cleaners' import { base58 } from '../../util/encoding' import { validateServer } from '../../util/validateServer' import { applyLoginPayload } from '../login/login' import { wasLoginStash } from '../login/login-stash' import { makeContext } from '../root' import { makeRepoPaths, saveChanges } from '../storage/repo' import { FakeDb } from './fake-db' import { makeFakeServer } from './fake-server' async function saveLogin(io, user) { const { lastLogin, server } = user const loginId = base64.parse(user.loginId) const loginKey = base64.parse(user.loginKey) const username = user.username == null ? undefined : fixUsername(user.username) // Save the stash: const stash = applyLoginPayload( { appId: '', lastLogin, loginId, pendingVouchers: [], username }, loginKey, // The correct cleaner is `asEdgeLoginDump`, // but the format is close enough that the other cleaner kinda fits: asLoginPayload(server) ) const path = `logins/${base58.stringify(loginId)}.json` await io.disklet .setText(path, JSON.stringify(wasLoginStash(stash))) .catch(() => {}) } async function saveRepo( io, syncKey, repo ) { const paths = makeRepoPaths(io, { dataKey: new Uint8Array(0), syncKey }) await saveChanges(paths.dataDisklet, repo) await paths.baseDisklet.setText( 'status.json', JSON.stringify({ lastSync: 1, lastHash: null }) ) } /** * Creates a fake Edge server for unit testing. */ export function makeFakeWorld( ios, logBackend, users ) { const { io, nativeIo } = ios const fakeDb = new FakeDb() const fakeServer = makeFakeServer(fakeDb) // Populate the fake database: for (const user of users) { fakeDb.setupLogin(asEdgeLoginDump(user.server)) for (const syncKey of Object.keys(user.repos)) { fakeDb.setupRepo(syncKey, asEdgeRepoDump(user.repos[syncKey])) } } const contexts = [] const out = { async close() { await Promise.all(contexts.map(context => context.close())) close(out) }, async makeEdgeContext(opts) { const { allowNetworkAccess = false, cleanDevice = false, extraFiles = {} } = opts const fakeFetch = makeFetchFunction(fakeServer) const fetch = !allowNetworkAccess ? fakeFetch : (uri, opts) => { try { validateServer(uri) // Throws for non-Edge servers. } catch (error) { return io.fetch(uri, opts) } return fakeFetch(uri, opts) } const fakeIo = { ...io, disklet: makeMemoryDisklet(), fetch } // Populate the fake disk: if (!cleanDevice) { for (const user of users) { await saveLogin(fakeIo, user) for (const syncKey of Object.keys(user.repos)) { await saveRepo( fakeIo, base16.parse(syncKey), asEdgeRepoDump(user.repos[syncKey]) ) } } } if (extraFiles != null) { for (const path of Object.keys(extraFiles)) { await fakeIo.disklet.setText(path, extraFiles[path]) } } const out = await makeContext({ io: fakeIo, nativeIo }, logBackend, { ...opts }) contexts.push(out) return out }, async goOffline(offline = true) { fakeServer.offline = offline }, async dumpFakeUser(account) { if (account.appId !== '') { throw new Error('Only root logins are dumpable.') } const loginId = base58.parse(account.rootLoginId) const loginKey = base58.parse(await account.getLoginKey()) // Find the data on the server: const login = fakeDb.getLoginById(loginId) if (login == null) { throw new Error(`Cannot find user ${account.rootLoginId}`) } // Figure out which repos to use: const syncKeys = [] for (const info of account.allKeys) { const keys = await account.getRawPrivateKey(info.id) if (keys.syncKey == null) continue syncKeys.push( base16.stringify(base64.parse(keys.syncKey)).toLowerCase() ) } const repos = {} for (const syncKey of syncKeys) { const repo = fakeDb.repos.get(syncKey) if (repo != null) repos[syncKey] = wasEdgeRepoDump(repo) } return { lastLogin: account.lastLogin, loginId: base64.stringify(loginId), loginKey: base64.stringify(loginKey), repos, server: wasEdgeLoginDump(fakeDb.dumpLogin(login)), username: account.username } } } bridgifyObject(out) return out }