You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.8 KiB
116 lines
2.8 KiB
// Native
|
|
const os = require('os')
|
|
|
|
// Packages
|
|
const {stringify: stringifyQuery} = require('querystring')
|
|
const chalk = require('chalk')
|
|
const fetch = require('node-fetch')
|
|
const {validate} = require('email-validator')
|
|
const readEmail = require('email-prompt')
|
|
const ora = require('ora')
|
|
|
|
// Ours
|
|
const pkg = require('./pkg')
|
|
const ua = require('./ua')
|
|
const cfg = require('./cfg')
|
|
const info = require('./utils/output/info')
|
|
const promptBool = require('./utils/input/prompt-bool')
|
|
|
|
async function getVerificationData(url, email) {
|
|
const tokenName = `Now CLI ${os.platform()}-${os.arch()} ${pkg.version} (${os.hostname()})`
|
|
const data = JSON.stringify({email, tokenName})
|
|
const res = await fetch(`${url}/now/registration`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Content-Length': Buffer.byteLength(data),
|
|
'User-Agent': ua
|
|
},
|
|
body: data
|
|
})
|
|
|
|
if (res.status !== 200) {
|
|
throw new Error('Verification error')
|
|
}
|
|
|
|
const body = await res.json()
|
|
return body
|
|
}
|
|
|
|
async function verify(url, email, verificationToken) {
|
|
const query = {
|
|
email,
|
|
token: verificationToken
|
|
}
|
|
|
|
const res = await fetch(`${url}/now/registration/verify?${stringifyQuery(query)}`, {
|
|
headers: {'User-Agent': ua}
|
|
})
|
|
const body = await res.json()
|
|
return body.token
|
|
}
|
|
|
|
function sleep(ms) {
|
|
return new Promise(resolve => {
|
|
setTimeout(resolve, ms)
|
|
})
|
|
}
|
|
|
|
async function register(url, {retryEmail = false} = {}) {
|
|
let email
|
|
try {
|
|
email = await readEmail({invalid: retryEmail})
|
|
} catch (err) {
|
|
process.stdout.write('\n')
|
|
throw err
|
|
}
|
|
|
|
process.stdout.write('\n')
|
|
|
|
info(`By continuing, you declare that you agree with ${chalk.bold('https://zeit.co/terms')} and ${chalk.bold('https://zeit.co/privacy.')}`)
|
|
if (!await promptBool('Continue?')) {
|
|
info('Aborted.')
|
|
process.exit() // eslint-disable-line unicorn/no-process-exit
|
|
}
|
|
|
|
if (!validate(email)) {
|
|
return register(url, {retryEmail: true})
|
|
}
|
|
|
|
const {token, securityCode} = await getVerificationData(url, email)
|
|
console.log(`> Please follow the link sent to ${chalk.bold(email)} to log in.`)
|
|
|
|
if (securityCode) {
|
|
console.log(`> Verify that the provided security code in the email matches ${chalk.cyan(chalk.bold(securityCode))}.`)
|
|
}
|
|
|
|
process.stdout.write('\n')
|
|
|
|
const spinner = ora({
|
|
text: 'Waiting for confirmation...',
|
|
color: 'black'
|
|
}).start()
|
|
|
|
let final
|
|
|
|
do {
|
|
await sleep(2500)
|
|
|
|
try {
|
|
final = await verify(url, email, token)
|
|
} catch (err) {}
|
|
} while (!final)
|
|
|
|
spinner.text = 'Confirmed email address!'
|
|
spinner.stopAndPersist('✔')
|
|
|
|
process.stdout.write('\n')
|
|
|
|
return {email, token: final}
|
|
}
|
|
|
|
module.exports = async function (url) {
|
|
const loginData = await register(url)
|
|
cfg.merge(loginData)
|
|
return loginData.token
|
|
}
|
|
|