mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-04-13 22:22:58 +00:00
Implement command permissions
This commit is contained in:
parent
507ff16050
commit
5e3d973725
@ -1,9 +1,8 @@
|
||||
_ = require('lodash')
|
||||
async = require('async')
|
||||
resin = require('../resin')
|
||||
authHooks = require('../hooks/auth')
|
||||
|
||||
exports.create = authHooks.failIfNotLoggedIn (name, program) ->
|
||||
exports.create = (name, program) ->
|
||||
async.waterfall [
|
||||
|
||||
(callback) ->
|
||||
@ -25,7 +24,7 @@ exports.create = authHooks.failIfNotLoggedIn (name, program) ->
|
||||
|
||||
], resin.errors.handle
|
||||
|
||||
exports.list = authHooks.failIfNotLoggedIn ->
|
||||
exports.list = ->
|
||||
resin.models.application.getAll (error, applications) ->
|
||||
resin.errors.handle(error) if error?
|
||||
|
||||
@ -38,7 +37,7 @@ exports.list = authHooks.failIfNotLoggedIn ->
|
||||
return application
|
||||
, [ 'ID', 'Name', 'Device Type', 'Online Devices', 'All Devices' ]
|
||||
|
||||
exports.info = authHooks.failIfNotLoggedIn (id) ->
|
||||
exports.info = (id) ->
|
||||
resin.models.application.get id, (error, application) ->
|
||||
resin.errors.handle(error) if error?
|
||||
|
||||
@ -48,12 +47,12 @@ exports.info = authHooks.failIfNotLoggedIn (id) ->
|
||||
return application
|
||||
, [ 'ID', 'Name', 'Device Type', 'Git Repository', 'Commit' ]
|
||||
|
||||
exports.restart = authHooks.failIfNotLoggedIn (id) ->
|
||||
exports.restart = (id) ->
|
||||
|
||||
resin.models.application.restart id, (error) ->
|
||||
resin.errors.handle(error) if error?
|
||||
|
||||
exports.remove = authHooks.failIfNotLoggedIn (id, program) ->
|
||||
exports.remove = (id, program) ->
|
||||
resin.ui.patterns.remove 'application', program.parent.yes, (callback) ->
|
||||
resin.models.application.remove(id, callback)
|
||||
, resin.errors.handle
|
||||
|
@ -1,7 +1,6 @@
|
||||
open = require('open')
|
||||
async = require('async')
|
||||
resin = require('../resin')
|
||||
authHooks = require('../hooks/auth')
|
||||
|
||||
exports.login = (credentials) ->
|
||||
async.waterfall [
|
||||
@ -17,7 +16,7 @@ exports.login = (credentials) ->
|
||||
|
||||
], resin.errors.handle
|
||||
|
||||
exports.logout = authHooks.failIfNotLoggedIn ->
|
||||
exports.logout = ->
|
||||
resin.auth.logout()
|
||||
|
||||
exports.signup = ->
|
||||
|
@ -1,7 +1,6 @@
|
||||
resin = require('../resin')
|
||||
authHooks = require('../hooks/auth')
|
||||
|
||||
exports.list = authHooks.failIfNotLoggedIn (applicationId) ->
|
||||
exports.list = (applicationId) ->
|
||||
resin.models.device.getAll applicationId, (error, devices) ->
|
||||
resin.errors.handle(error) if error?
|
||||
|
||||
@ -15,11 +14,11 @@ exports.list = authHooks.failIfNotLoggedIn (applicationId) ->
|
||||
return device
|
||||
, [ 'ID', 'Name', 'Device Type', 'Is Online', 'IP Address', 'Application', 'Status', 'Last Seen' ]
|
||||
|
||||
exports.remove = authHooks.failIfNotLoggedIn (id, program) ->
|
||||
exports.remove = (id, program) ->
|
||||
resin.ui.patterns.remove 'device', program.parent.yes, (callback) ->
|
||||
resin.models.device.remove(id, callback)
|
||||
, resin.errors.handle
|
||||
|
||||
exports.identify = authHooks.failIfNotLoggedIn (uuid) ->
|
||||
exports.identify = (uuid) ->
|
||||
resin.models.device.identify uuid, (error) ->
|
||||
resin.errors.handle(error) if error?
|
||||
|
@ -1,13 +1,12 @@
|
||||
_ = require('lodash')
|
||||
resin = require('../resin')
|
||||
authHooks = require('../hooks/auth')
|
||||
|
||||
SYSTEM_VAR_REGEX = /^RESIN_/
|
||||
|
||||
isSystemVariable = (environmentVariable) ->
|
||||
SYSTEM_VAR_REGEX.test(environmentVariable.name)
|
||||
|
||||
exports.list = authHooks.failIfNotLoggedIn (program) ->
|
||||
exports.list = (program) ->
|
||||
applicationId = program.parent?.application
|
||||
|
||||
if not applicationId?
|
||||
@ -21,7 +20,7 @@ exports.list = authHooks.failIfNotLoggedIn (program) ->
|
||||
|
||||
resin.log.out(resin.ui.widgets.table.horizontal(environmentVariables))
|
||||
|
||||
exports.remove = authHooks.failIfNotLoggedIn (id, program) ->
|
||||
exports.remove = (id, program) ->
|
||||
resin.ui.patterns.remove 'environment variable', program.parent.yes, (callback) ->
|
||||
resin.models.environmentVariables.remove(id, callback)
|
||||
, resin.errors.handle
|
||||
|
@ -1,9 +1,8 @@
|
||||
_ = require('lodash')
|
||||
resin = require('../resin')
|
||||
authHooks = require('../hooks/auth')
|
||||
helpers = require('../helpers/helpers')
|
||||
|
||||
exports.list = authHooks.failIfNotLoggedIn ->
|
||||
exports.list = ->
|
||||
resin.server.get resin.config.urls.keys, (error, response, keys) ->
|
||||
resin.errors.handle(error) if error?
|
||||
resin.log.out resin.ui.widgets.table.horizontal keys, (key) ->
|
||||
@ -11,7 +10,7 @@ exports.list = authHooks.failIfNotLoggedIn ->
|
||||
return key
|
||||
, [ 'ID', 'Title' ]
|
||||
|
||||
exports.info = authHooks.failIfNotLoggedIn (id) ->
|
||||
exports.info = (id) ->
|
||||
id = _.parseInt(id)
|
||||
|
||||
# TODO: We don't have a way to query a single ssh key yet.
|
||||
@ -26,7 +25,7 @@ exports.info = authHooks.failIfNotLoggedIn (id) ->
|
||||
key.public_key = '\n' + helpers.formatLongString(key.public_key, resin.config.sshKeyWidth)
|
||||
resin.log.out(resin.ui.widgets.table.vertical(key, _.identity, [ 'ID', 'Title', 'Public Key' ]))
|
||||
|
||||
exports.remove = authHooks.failIfNotLoggedIn (id, program) ->
|
||||
exports.remove = (id, program) ->
|
||||
resin.ui.patterns.remove 'key', program.parent.yes, (callback) ->
|
||||
resin.server.delete("/user/keys/#{id}", callback)
|
||||
, resin.errors.handle
|
||||
|
@ -1,5 +1,5 @@
|
||||
open = require('open')
|
||||
authHooks = require('../hooks/auth')
|
||||
resin = require('../resin')
|
||||
|
||||
exports.preferences = authHooks.failIfNotLoggedIn ->
|
||||
exports.preferences = ->
|
||||
open(resin.config.urls.preferences)
|
||||
|
@ -39,6 +39,7 @@ resin.cli.addCommand
|
||||
command: 'logout'
|
||||
description: 'logout from resin.io'
|
||||
action: actions.auth.logout
|
||||
permission: 'user'
|
||||
|
||||
resin.cli.addCommand
|
||||
command: 'signup'
|
||||
@ -50,40 +51,47 @@ resin.cli.addResource
|
||||
name: 'app'
|
||||
displayName: 'application'
|
||||
actions: actions.app
|
||||
permission: 'user'
|
||||
|
||||
resin.cli.addCommand
|
||||
command: 'app:restart <id>'
|
||||
description: 'restart an application'
|
||||
action: actions.app.restart
|
||||
permission: 'user'
|
||||
|
||||
# ---------- Device Module ----------
|
||||
resin.cli.addResource
|
||||
name: 'device'
|
||||
displayName: 'device'
|
||||
actions: actions.device
|
||||
permission: 'user'
|
||||
|
||||
resin.cli.addCommand
|
||||
command: 'device:identify <uuid>'
|
||||
description: 'identify a device with a UUID'
|
||||
action: actions.device.identify
|
||||
permission: 'user'
|
||||
|
||||
# ---------- Preferences Module ----------
|
||||
resin.cli.addCommand
|
||||
command: 'preferences'
|
||||
description: 'open preferences form'
|
||||
action: actions.preferences.preferences
|
||||
permission: 'user'
|
||||
|
||||
# ---------- Keys Module ----------
|
||||
resin.cli.addResource
|
||||
name: 'key'
|
||||
displayName: 'ssh key'
|
||||
actions: actions.keys
|
||||
permission: 'user'
|
||||
|
||||
# ---------- Env Module ----------
|
||||
resin.cli.addResource
|
||||
name: 'env'
|
||||
displayName: 'environment variable'
|
||||
actions: actions.env
|
||||
permission: 'user'
|
||||
|
||||
resin.data.prefix.set resin.config.dataPrefix, (error) ->
|
||||
resin.errors.handle(error) if error?
|
||||
|
@ -1,10 +1,9 @@
|
||||
_ = require('lodash')
|
||||
resin = require('../resin')
|
||||
auth = require('../auth/auth')
|
||||
|
||||
exports.failIfNotLoggedIn = (fn, onError) ->
|
||||
exports.user = (fn, onError) ->
|
||||
return ->
|
||||
args = arguments
|
||||
resin.auth.isLoggedIn (isLoggedIn) ->
|
||||
auth.isLoggedIn (isLoggedIn) ->
|
||||
|
||||
if not isLoggedIn
|
||||
error = new Error('You have to log in')
|
@ -2,14 +2,16 @@ _ = require('lodash')
|
||||
nock = require('nock')
|
||||
sinon = require('sinon')
|
||||
expect = require('chai').expect
|
||||
resin = require('../resin')
|
||||
authHooks = require('./auth')
|
||||
johnDoeFixture = require('../../tests/fixtures/johndoe')
|
||||
mock = require('../../tests/utils/mock')
|
||||
data = require('../data/data')
|
||||
auth = require('../auth/auth')
|
||||
config = require('../config')
|
||||
cliPermissions = require('./cli-permissions')
|
||||
johnDoeFixture = require('../../../tests/fixtures/johndoe')
|
||||
mock = require('../../../tests/utils/mock')
|
||||
|
||||
describe 'Auth Hooks:', ->
|
||||
describe 'CLI Permissions:', ->
|
||||
|
||||
describe '#failIfNotLoggedIn()', ->
|
||||
describe '#user()', ->
|
||||
|
||||
before ->
|
||||
mock.connection.init()
|
||||
@ -19,7 +21,7 @@ describe 'Auth Hooks:', ->
|
||||
|
||||
beforeEach (done) ->
|
||||
mock.fs.init()
|
||||
resin.data.prefix.set(resin.config.dataPrefix, done)
|
||||
data.prefix.set(config.dataPrefix, done)
|
||||
|
||||
afterEach ->
|
||||
mock.fs.restore()
|
||||
@ -27,18 +29,18 @@ describe 'Auth Hooks:', ->
|
||||
describe 'if not logged in', ->
|
||||
|
||||
beforeEach (done) ->
|
||||
resin.auth.logout(done)
|
||||
auth.logout(done)
|
||||
|
||||
it 'should not call the function', (done) ->
|
||||
spy = sinon.spy()
|
||||
authHooks.failIfNotLoggedIn(spy, _.noop)()
|
||||
cliPermissions.user(spy, _.noop)()
|
||||
|
||||
_.defer ->
|
||||
expect(spy).to.not.have.been.called
|
||||
done()
|
||||
|
||||
it 'it should call the second function with an error', (done) ->
|
||||
func = authHooks.failIfNotLoggedIn _.noop, (error) ->
|
||||
func = cliPermissions.user _.noop, (error) ->
|
||||
expect(error).to.be.an.instanceof(Error)
|
||||
done()
|
||||
func()
|
||||
@ -48,7 +50,7 @@ describe 'Auth Hooks:', ->
|
||||
# (auth.isLoggedIn). A try/catch works, but it still results
|
||||
# in the error being printed in Mocha reporter.
|
||||
xit 'should throw an error if no error handler function', ->
|
||||
func = authHooks.failIfNotLoggedIn(_.noop)
|
||||
func = cliPermissions.user(_.noop)
|
||||
try
|
||||
func()
|
||||
catch error
|
||||
@ -57,17 +59,17 @@ describe 'Auth Hooks:', ->
|
||||
describe 'if logged in', ->
|
||||
|
||||
beforeEach (done) ->
|
||||
nock(resin.config.remoteUrl)
|
||||
nock(config.remoteUrl)
|
||||
.post('/login_', johnDoeFixture.credentials)
|
||||
.reply(200, johnDoeFixture.token)
|
||||
|
||||
resin.auth.login(johnDoeFixture.credentials, done)
|
||||
auth.login(johnDoeFixture.credentials, done)
|
||||
|
||||
it 'should call the function with the correct arguments', (done) ->
|
||||
args = [ 1, 2, 3, 'foo', 'bar' ]
|
||||
|
||||
spy = sinon.spy()
|
||||
authHooks.failIfNotLoggedIn(spy, _.noop).apply(null, args)
|
||||
cliPermissions.user(spy, _.noop).apply(null, args)
|
||||
|
||||
_.defer ->
|
||||
expect(spy).to.have.been.calledWith(args...)
|
||||
@ -75,7 +77,7 @@ describe 'Auth Hooks:', ->
|
||||
|
||||
it 'should not call the second function', (done) ->
|
||||
spy = sinon.spy()
|
||||
authHooks.failIfNotLoggedIn(_.noop, spy)()
|
||||
cliPermissions.user(_.noop, spy)()
|
||||
|
||||
_.defer ->
|
||||
expect(spy).to.not.have.been.called
|
@ -3,6 +3,7 @@ program = require('commander')
|
||||
pluralize = require('pluralize')
|
||||
indefiniteArticle = require('indefinite-article')
|
||||
log = require('../log/log')
|
||||
cliPermissions = require('./cli-permissions')
|
||||
|
||||
exports.getArgument = (name) ->
|
||||
return program[name]
|
||||
@ -17,11 +18,23 @@ exports.setVersion = (version) ->
|
||||
action: ->
|
||||
log.out(version)
|
||||
|
||||
applyPermissions = (permission, action, onError) ->
|
||||
permissionFunction = cliPermissions[permission]
|
||||
if not _.isFunction(permissionFunction)
|
||||
throw new Error("Invalid permission #{permission}")
|
||||
return permissionFunction(action, onError)
|
||||
|
||||
exports.addCommand = (options = {}) ->
|
||||
|
||||
if options.permission?
|
||||
action = applyPermissions(options.permission, options.action, options.onError)
|
||||
else
|
||||
action = options.action
|
||||
|
||||
program
|
||||
.command(options.command)
|
||||
.description(options.description)
|
||||
.action(options.action)
|
||||
.action(action)
|
||||
|
||||
return program
|
||||
|
||||
@ -40,24 +53,28 @@ exports.addResource = (options = {}) ->
|
||||
command: "#{options.name}:create <name>"
|
||||
description: "create #{nameArticle} #{options.displayName}"
|
||||
action: options.actions.create
|
||||
permission: options.permission
|
||||
|
||||
if _.isFunction(options.actions.list)
|
||||
exports.addCommand
|
||||
command: "#{pluralizedName}"
|
||||
description: "list all #{pluralizedDisplayName}"
|
||||
action: options.actions.list
|
||||
permission: options.permission
|
||||
|
||||
if _.isFunction(options.actions.info)
|
||||
exports.addCommand
|
||||
command: "#{options.name} <id>"
|
||||
description: "list a single #{options.displayName}"
|
||||
action: options.actions.info
|
||||
permission: options.permission
|
||||
|
||||
if _.isFunction(options.actions.remove)
|
||||
exports.addCommand
|
||||
command: "#{options.name}:rm <id>"
|
||||
description: "remove #{nameArticle} #{options.displayName}"
|
||||
action: options.actions.remove
|
||||
permission: options.permission
|
||||
|
||||
exports.parse = (argv) ->
|
||||
program.parse(argv)
|
||||
|
Loading…
x
Reference in New Issue
Block a user