@dotenvx/dotenvx-radar
Version:
Dotenvx Radar
116 lines (96 loc) • 3.41 kB
JavaScript
const open = require('open')
const { logger } = require('@dotenvx/dotenvx')
const Session = require('./../../db/session')
const clipboardy = require('./../../lib/helpers/clipboardy')
const { createSpinner } = require('./../../lib/helpers/createSpinner')
const confirm = require('./../../lib/helpers/confirm')
const truncate = require('./../../lib/helpers/truncate')
const formatCode = require('./../../lib/helpers/formatCode')
const spinner = createSpinner('waiting on browser authorization')
// api calls
const PostOauthToken = require('./../../lib/api/postOauthToken')
const PostOauthDeviceCode = require('./../../lib/api/postOauthDeviceCode')
async function pollTokenUrl (hostname, deviceCode, interval) {
logger.debug(`POST ${hostname} with deviceCode ${deviceCode} at interval ${interval}`)
const sesh = new Session()
while (true) {
try {
let data
try {
data = await new PostOauthToken(hostname, deviceCode).run()
if (data.access_token) {
const id = data.id
const username = data.username
const accessToken = data.access_token
// log in user
sesh.login(hostname, id, username, accessToken)
spinner.succeed(`logged in [${username}] to this device and activated token [${truncate(accessToken, 11)}]`)
// logger.help('⮕ next run [dotenvx-radar sync]')
process.exit(0)
} else {
await new Promise(resolve => setTimeout(resolve, interval * 1000))
}
} catch (error) {
// continue polling if authorization_pending
if (error.code === 'authorization_pending') {
const newInterval = interval + 1 // grow the interval
await new Promise(resolve => setTimeout(resolve, newInterval * 1000))
} else {
throw error
}
}
} catch (error) {
spinner.stop()
if (error.message) {
logger.error(error.message)
} else {
logger.error(error)
}
if (error.help) {
logger.help(error.help)
}
process.exit(1)
}
}
}
async function login () {
const options = this.opts()
logger.debug(`options: ${JSON.stringify(options)}`)
const hostname = options.hostname
try {
const data = await new PostOauthDeviceCode(hostname).run()
const deviceCode = data.device_code
const userCode = data.user_code
const verificationUri = data.verification_uri
const verificationUriComplete = data.verification_uri_complete
const interval = data.interval
try { clipboardy.writeSync(userCode) } catch (_e) {}
// begin polling
pollTokenUrl(hostname, deviceCode, interval)
logger.info(`press Enter to open [${verificationUri}] and enter code [${formatCode(userCode)}]...`)
spinner.start()
// // optionally allow user to open browser
const answer = await confirm({ message: `press Enter to open [${verificationUri}] and enter code [${formatCode(userCode)}]...` })
if (answer) {
await open(verificationUriComplete)
} else {
spinner.stop()
process.exit(1)
}
} catch (error) {
spinner.stop()
if (error.message) {
logger.error(error.message)
} else {
logger.error(error)
}
if (error.help) {
logger.help(error.help)
}
if (error.stack) {
logger.debug(error.stack)
}
process.exit(1)
}
}
module.exports = login