UNPKG

edge-core-js

Version:

Edge account & wallet management library

155 lines (130 loc) 4.34 kB
function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }import { wasCreateLoginPayload } from '../../types/server-cleaners' import { asMaybeUsernameError, } from '../../types/types' import { encrypt } from '../../util/crypto/crypto' import { makeKeysKit } from './keys' import { loginFetch } from './login-fetch' import { makeSecretKit } from './login-secret' import { hashUsername } from './login-selectors' import { saveStash } from './login-stash' import { makeUsernameKit } from './login-username' import { makePasswordKit } from './password' import { makeChangePin2Kit } from './pin2' /** * Determines whether or not a username is available. */ export async function usernameAvailable( ai, username, challengeId ) { const userId = await hashUsername(ai, username) const request = { challengeId, userId } return await loginFetch(ai, 'POST', '/v2/login', request) .then(reply => false) // It's not available if we can hit it! .catch((error) => { if (asMaybeUsernameError(error) != null) return true throw error }) } /** * Assembles all the data needed to create a new login. */ export async function makeCreateKit( ai, parentSessionKey, appId, opts ) { const { keyInfo, password, pin, username } = opts const { io } = ai.props // For crash errors: ai.props.log.breadcrumb('makeCreateKit', {}) // Figure out login identity: const isRoot = parentSessionKey == null const loginId = io.random(32) const loginKey = io.random(32) const sessionKey = { loginId, loginKey } // Create the basic login object, but without any authentication methods: const login = { appId, lastLogin: new Date(), loginId, loginKey, isRoot, pendingVouchers: [], children: [] } const secretKit = makeSecretKit(ai, login) let keysKit let parentBox let passwordKit let pin2Kit let usernameKit // Set up optional login methods: if (keyInfo != null) { keysKit = makeKeysKit(ai, sessionKey, [keyInfo]) } if (parentSessionKey != null) { parentBox = encrypt(io, loginKey, parentSessionKey.loginKey) } if (password != null && username != null) { passwordKit = await makePasswordKit(ai, login, username, password) } if (pin != null) { pin2Kit = makeChangePin2Kit(ai, login, username, pin, true) } if (isRoot && username != null) { usernameKit = await makeUsernameKit(ai, login, username) } // Bundle everything: const kit = { loginId, server: { ...wasCreateLoginPayload({ appId, loginId, parentBox }), ..._optionalChain([keysKit, 'optionalAccess', _ => _.server]), ..._optionalChain([passwordKit, 'optionalAccess', _2 => _2.server]), ..._optionalChain([pin2Kit, 'optionalAccess', _3 => _3.server]), ...secretKit.server, ..._optionalChain([usernameKit, 'optionalAccess', _4 => _4.server]) }, serverPath: '/v2/login/create', stash: { appId, loginId, parentBox, ..._optionalChain([keysKit, 'optionalAccess', _5 => _5.stash]), ..._optionalChain([passwordKit, 'optionalAccess', _6 => _6.stash]), ..._optionalChain([pin2Kit, 'optionalAccess', _7 => _7.stash]), ...secretKit.stash, ..._optionalChain([usernameKit, 'optionalAccess', _8 => _8.stash]) } } return { kit, sessionKey } } /** * Creates a new login on the auth server. */ export async function createLogin( ai, accountOpts, opts ) { const { challengeId, now = new Date() } = accountOpts // For crash errors: ai.props.log.breadcrumb('createLogin', {}) const { kit, sessionKey } = await makeCreateKit(ai, undefined, '', opts) const request = { challengeId, data: kit.server } await loginFetch(ai, 'POST', kit.serverPath, request) kit.stash.lastLogin = now await saveStash(ai, kit.stash ) return sessionKey }