mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-22 23:12:22 +00:00
174 lines
4.8 KiB
CoffeeScript
174 lines
4.8 KiB
CoffeeScript
###
|
|
Copyright 2016 Resin.io
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
###
|
|
|
|
_ = require('lodash')
|
|
Promise = require('bluebird')
|
|
form = require('resin-cli-form')
|
|
visuals = require('resin-cli-visuals')
|
|
resin = require('resin-sdk-preconfigured')
|
|
chalk = require('chalk')
|
|
validation = require('./validation')
|
|
messages = require('./messages')
|
|
|
|
exports.authenticate = (options) ->
|
|
return form.run [
|
|
message: 'Email:'
|
|
name: 'email'
|
|
type: 'input'
|
|
validate: validation.validateEmail
|
|
,
|
|
message: 'Password:'
|
|
name: 'password'
|
|
type: 'password'
|
|
],
|
|
override: options
|
|
.then(resin.auth.login)
|
|
.then(resin.auth.twoFactor.isPassed)
|
|
.then (isTwoFactorAuthPassed) ->
|
|
return if isTwoFactorAuthPassed
|
|
return form.ask
|
|
message: 'Two factor auth challenge:'
|
|
name: 'code'
|
|
type: 'input'
|
|
.then(resin.auth.twoFactor.challenge)
|
|
.catch (error) ->
|
|
resin.auth.logout().then ->
|
|
if error.name is 'ResinRequestError' and error.statusCode is 401
|
|
throw new Error('Invalid two factor authentication code')
|
|
throw error
|
|
|
|
exports.askLoginType = ->
|
|
return form.ask
|
|
message: 'How would you like to login?'
|
|
name: 'loginType'
|
|
type: 'list'
|
|
choices: [
|
|
name: 'Web authorization (recommended)'
|
|
value: 'web'
|
|
,
|
|
name: 'Credentials'
|
|
value: 'credentials'
|
|
,
|
|
name: 'Authentication token'
|
|
value: 'token'
|
|
,
|
|
name: 'I don\'t have a Resin account!'
|
|
value: 'register'
|
|
]
|
|
|
|
exports.selectDeviceType = ->
|
|
resin.models.device.getSupportedDeviceTypes().then (deviceTypes) ->
|
|
return form.ask
|
|
message: 'Device Type'
|
|
type: 'list'
|
|
choices: deviceTypes
|
|
|
|
exports.confirm = (yesOption, message) ->
|
|
Promise.try ->
|
|
return true if yesOption
|
|
return form.ask
|
|
message: message
|
|
type: 'confirm'
|
|
default: false
|
|
.then (confirmed) ->
|
|
if not confirmed
|
|
throw new Error('Aborted')
|
|
|
|
exports.selectApplication = (filter) ->
|
|
resin.models.application.hasAny().then (hasAnyApplications) ->
|
|
if not hasAnyApplications
|
|
throw new Error('You don\'t have any applications')
|
|
|
|
return resin.models.application.getAll()
|
|
.filter(filter or _.constant(true))
|
|
.then (applications) ->
|
|
return form.ask
|
|
message: 'Select an application'
|
|
type: 'list'
|
|
choices: _.map applications, (application) ->
|
|
return {
|
|
name: "#{application.app_name} (#{application.device_type})"
|
|
value: application.app_name
|
|
}
|
|
|
|
exports.selectOrCreateApplication = ->
|
|
resin.models.application.hasAny().then (hasAnyApplications) ->
|
|
return if not hasAnyApplications
|
|
resin.models.application.getAll().then (applications) ->
|
|
applications = _.map applications, (application) ->
|
|
return {
|
|
name: "#{application.app_name} (#{application.device_type})"
|
|
value: application.app_name
|
|
}
|
|
|
|
applications.unshift
|
|
name: 'Create a new application'
|
|
value: null
|
|
|
|
return form.ask
|
|
message: 'Select an application'
|
|
type: 'list'
|
|
choices: applications
|
|
.then (application) ->
|
|
return application if application?
|
|
form.ask
|
|
message: 'Choose a Name for your new application'
|
|
type: 'input'
|
|
validate: validation.validateApplicationName
|
|
|
|
exports.awaitDevice = (uuid) ->
|
|
resin.models.device.getName(uuid).then (deviceName) ->
|
|
spinner = new visuals.Spinner("Waiting for #{deviceName} to come online")
|
|
|
|
poll = ->
|
|
resin.models.device.isOnline(uuid).then (isOnline) ->
|
|
if isOnline
|
|
spinner.stop()
|
|
console.info("The device **#{deviceName}** is online!")
|
|
return
|
|
else
|
|
|
|
# Spinner implementation is smart enough to
|
|
# not start again if it was already started
|
|
spinner.start()
|
|
|
|
return Promise.delay(3000).then(poll)
|
|
|
|
console.info("Waiting for #{deviceName} to connect to resin...")
|
|
poll().return(uuid)
|
|
|
|
exports.inferOrSelectDevice = (preferredUuid) ->
|
|
resin.models.device.getAll()
|
|
.filter (device) ->
|
|
device.is_online
|
|
.then (onlineDevices) ->
|
|
if _.isEmpty(onlineDevices)
|
|
throw new Error('You don\'t have any devices online')
|
|
|
|
return form.ask
|
|
message: 'Select a device'
|
|
type: 'list'
|
|
default: if preferredUuid in _.map(onlineDevices, 'uuid') then preferredUuid else onlineDevices[0].uuid
|
|
choices: _.map onlineDevices, (device) ->
|
|
return {
|
|
name: "#{device.name or 'Untitled'} (#{device.uuid.slice(0, 7)})"
|
|
value: device.uuid
|
|
}
|
|
|
|
exports.printErrorMessage = (message) ->
|
|
console.error(chalk.red(message))
|
|
console.error(chalk.red("\n#{messages.getHelp}\n"))
|