aptible-cli 0.6.7 → 0.6.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7800411b1c246c299e73b915d9352b3f3ba2ce47
4
- data.tar.gz: 84b8ca4a819ba20f99887b10af6fb6921256fe80
3
+ metadata.gz: 1a3f6b5e9a9f9f325832789f7bbac423de2276c8
4
+ data.tar.gz: 328b06f1dcf9cb13c0df4f63f587fb4b79145a57
5
5
  SHA512:
6
- metadata.gz: 6b1d82455c6c2d2eea71366923ce913dc6a2678bc1aaef7222177c643d44088f14273aac3441bad4225044668c06f343aa52379cbb0241f1591f596437dc61cf
7
- data.tar.gz: 0bddfeb029c33710957829594e08635c5e42811c46fd0b45dfd06994eb1a7e13c2c1a50173d4f387fd01f6ab26275aed9508aa21d0e48647abd29fbffb473c94
6
+ metadata.gz: 8618af8eaf81ca409c8dfd680a00744f265a72da22d87767d679b93c6deadc6d8edf2951fcd488521d68a92ffdbb60f2969a995fb5ad0f3c30afc0ee2858ff48
7
+ data.tar.gz: 9da5825e8c2d8e2476ffce6268406f421cc357edd7fc8290801b1b342fe760351082f0f4864e782b113a0a1e8291b3226d815af3b50d23d0438cc0b97106e5d9
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ['lib']
22
22
 
23
23
  spec.add_dependency 'aptible-api', '>= 0.9.5'
24
+ spec.add_dependency 'aptible-auth', '>= 0.11.3'
24
25
  spec.add_dependency 'thor', '>= 0.19.0'
25
26
  spec.add_dependency 'git'
26
27
  spec.add_dependency 'term-ansicolor'
@@ -21,6 +21,8 @@ require_relative 'subcommands/ssh'
21
21
 
22
22
  module Aptible
23
23
  module CLI
24
+ TOKEN_EXPIRY_WITH_OTP = 12 * 60 * 60 # 12 hours
25
+
24
26
  class Agent < Thor
25
27
  include Thor::Actions
26
28
 
@@ -48,15 +50,30 @@ module Aptible
48
50
  desc 'login', 'Log in to Aptible'
49
51
  option :email
50
52
  option :password
53
+ option :otp_token, desc: 'A token generated by your second-factor app'
51
54
  def login
52
55
  email = options[:email] || ask('Email: ')
53
56
  password = options[:password] || ask('Password: ', echo: false)
54
57
  puts ''
55
58
 
59
+ token_options = { email: email, password: password }
60
+
61
+ otp_token = options[:otp_token]
62
+ token_options[:otp_token] = otp_token if otp_token
63
+
56
64
  begin
57
- token = Aptible::Auth::Token.create(email: email, password: password)
58
- rescue OAuth2::Error
59
- raise Thor::Error, 'Could not authenticate with given credentials'
65
+ token_options[:expires_in] = TOKEN_EXPIRY_WITH_OTP \
66
+ if token_options[:otp_token]
67
+ token = Aptible::Auth::Token.create(token_options)
68
+ rescue OAuth2::Error => e
69
+ if e.code == 'otp_token_required'
70
+ token_options[:otp_token] = options[:otp_token] ||
71
+ ask('2FA Token: ')
72
+ retry
73
+ end
74
+
75
+ raise Thor::Error, 'Could not authenticate with given credentials: ' \
76
+ "#{e.code}"
60
77
  end
61
78
 
62
79
  save_token(token.access_token)
@@ -1,5 +1,5 @@
1
1
  module Aptible
2
2
  module CLI
3
- VERSION = '0.6.7'
3
+ VERSION = '0.6.8'
4
4
  end
5
5
  end
@@ -15,8 +15,12 @@ describe Aptible::CLI::Agent do
15
15
  describe '#login' do
16
16
  let(:token) { double('Aptible::Auth::Token') }
17
17
 
18
- before { OAuth2::Error.send :define_method, :initialize, -> {} }
18
+ before do
19
+ m = -> (code) { @code = code }
20
+ OAuth2::Error.send :define_method, :initialize, m
21
+ end
19
22
  before { token.stub(:access_token) { 'access_token' } }
23
+ before { subject.stub(:puts) {} }
20
24
 
21
25
  it 'should save a token to ~/.aptible/tokens' do
22
26
  Aptible::Auth::Token.stub(:create) { token }
@@ -25,10 +29,10 @@ describe Aptible::CLI::Agent do
25
29
  end
26
30
 
27
31
  it 'should raise an error if authentication fails' do
28
- Aptible::Auth::Token.stub(:create).and_raise OAuth2::Error
32
+ Aptible::Auth::Token.stub(:create).and_raise(OAuth2::Error, 'foo')
29
33
  expect do
30
34
  subject.login
31
- end.to raise_error 'Could not authenticate with given credentials'
35
+ end.to raise_error 'Could not authenticate with given credentials: foo'
32
36
  end
33
37
 
34
38
  it 'should use command line arguments if passed' do
@@ -37,5 +41,70 @@ describe Aptible::CLI::Agent do
37
41
  expect(Aptible::Auth::Token).to receive(:create).with(options) { token }
38
42
  subject.login
39
43
  end
44
+
45
+ context 'with OTP' do
46
+ let(:email) { 'foo@example.org' }
47
+ let(:password) { 'bar' }
48
+ let(:token) { '123456' }
49
+
50
+ context 'with options' do
51
+ before do
52
+ allow(subject).to receive(:options)
53
+ .and_return(email: email, password: password, otp_token: token)
54
+ end
55
+
56
+ it 'should authenticate without otp_token_required feedback' do
57
+ expect(Aptible::Auth::Token).to receive(:create)
58
+ .with(email: email, password: password, otp_token: token,
59
+ expires_in: Aptible::CLI::TOKEN_EXPIRY_WITH_OTP)
60
+ .once
61
+ .and_return(token)
62
+
63
+ subject.login
64
+ end
65
+ end
66
+
67
+ context 'with prompts' do
68
+ before do
69
+ [
70
+ [['Email: '], email],
71
+ [['Password: ', echo: false], password],
72
+ [['2FA Token: '], token]
73
+ ].each do |prompt, val|
74
+ expect(subject).to receive(:ask).with(*prompt).once.and_return(val)
75
+ end
76
+ end
77
+
78
+ it 'should prompt for an OTP token and use it' do
79
+ expect(Aptible::Auth::Token).to receive(:create)
80
+ .with(email: email, password: password)
81
+ .once
82
+ .and_raise(OAuth2::Error, 'otp_token_required')
83
+
84
+ expect(Aptible::Auth::Token).to receive(:create)
85
+ .with(email: email, password: password, otp_token: token,
86
+ expires_in: Aptible::CLI::TOKEN_EXPIRY_WITH_OTP)
87
+ .once
88
+ .and_return(token)
89
+
90
+ subject.login
91
+ end
92
+
93
+ it 'should not retry non-OTP errors.' do
94
+ expect(Aptible::Auth::Token).to receive(:create)
95
+ .with(email: email, password: password)
96
+ .once
97
+ .and_raise(OAuth2::Error, 'otp_token_required')
98
+
99
+ expect(Aptible::Auth::Token).to receive(:create)
100
+ .with(email: email, password: password, otp_token: token,
101
+ expires_in: Aptible::CLI::TOKEN_EXPIRY_WITH_OTP)
102
+ .once
103
+ .and_raise(OAuth2::Error, 'foo')
104
+
105
+ expect { subject.login }.to raise_error(/Could not authenticate/)
106
+ end
107
+ end
108
+ end
40
109
  end
41
110
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aptible-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7
4
+ version: 0.6.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-16 00:00:00.000000000 Z
11
+ date: 2016-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aptible-api
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.9.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: aptible-auth
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.11.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.11.3
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: thor
29
43
  requirement: !ruby/object:Gem::Requirement