finish implementing the authenticate command (+ specs) + refactor the other specs to match the new rspec syntax

did committed Apr 08, 2015
commit 3538424449745978644e2e6df769f88198226984
Showing 10 changed files with 392 additions and 63 deletions
.rspec +0 -1
@@ @@ -1,2 +1 @@
--colour
- --backtrace
locomotive/wagon/commands/authenticate_command.rb b/lib/locomotive/wagon/commands/authenticate_command.rb +63 -44
@@ @@ -1,3 +1,6 @@
+ require 'locomotive/coal'
+ require 'netrc'
+
module Locomotive::Wagon
class AuthenticateCommand < Struct.new(:platform_url, :email, :password, :shell)
@@ @@ -7,54 +10,70 @@ module Locomotive::Wagon
end
def authenticate
- puts "[auth] #{platform_url.inspect} / #{email.inspect} / #{password.inspect}"
- puts 'YOUPI'
-
- # require 'locomotive/wagon/misc/hosting_api'
- # require 'locomotive/coal'
- # require 'netrc'
-
- # api_key = nil
- # api = Locomotive::HostingAPI.new(email: email, password: password)
-
- # if api.authenticated?
- # # existing account
- # api_key = api.api_key
- # shell.say "You have been successfully authenticated.", :green
- # else
- # # new account?
- # shell.say "No account found for #{email} or invalid credentials", :yellow
-
- # if shell.yes?('Do you want to create a new account? [Y/N]')
- # name = shell.ask 'What is your name?'
-
- # account = api.create_account(name: name, email: email, password: password)
-
- # if account.success?
- # shell.say "Your account has been successfully created.", :green
- # api_key = account['api_key']
- # else
- # shell.say "We were unable to create your account, reason(s): #{account.error_messages.join(', ')}", :red
- # end
- # end
- # end
-
- # if api_key
- # # record the credentials
- # netrc = Netrc.read
- # netrc[api.domain_with_port] = email, api_key
- # netrc.save
- # else
- # shell.say "We were unable to authenticate you on our platform.", :red
- # end
-
- true
+ if api_key = fetch_api_key
+ record_credentials(api_key)
+ else
+ shell.say "Sorry, we were unable to authenticate you on \"#{platform_url}\"", :red
+ end
+
+ !api_key.nil?
+ end
+
+ def fetch_api_key
+ if my_account
+ my_account.api_key
+ else
+ shell.say "No account found for #{email} or invalid credentials", :yellow
+
+ # shall we create a new account?
+ if shell.yes?('Do you want to create a new account? [Y/N]')
+ create_account
+ else
+ false
+ end
+ end
+ end
+
+ def create_account
+ name = shell.ask 'What is your name?'
+
+ begin
+ account = client.my_account.create(name: name, email: email, password: password)
+ shell.say "Your account has been successfully created.", :green
+ account.api_key
+ rescue Locomotive::Coal::Error => e
+ shell.say "We were unable to create your account, reason(s): #{e.message}", :red
+ false
+ end
+ end
+
+ def record_credentials(api_key)
+ uri = URI(platform_url)
+ key = "#{uri.host}:#{uri.port}"
+
+ netrc = Netrc.read
+ netrc[key] = email, api_key
+ netrc.save
end
private
- def api_key_from_credentials
- # client = Locomotive::Coal::Client.new('http://www.myengine.dev/locomotive/api', { email: <EMAIL>, api_key: <API KEY> })
+ def my_account
+ begin
+ client.my_account.get
+ rescue Locomotive::Coal::UnauthorizedError
+ nil
+ end
+ end
+
+ def client
+ @client ||= Locomotive::Coal::Client.new(api_url, email: email, password: password)
+ end
+
+ def api_url
+ uri = URI(platform_url)
+ uri.merge!('/locomotive/api/v3') if uri.path == '/' || uri.path == ''
+ uri.to_s
end
end
spec/fixtures/cassettes/authenticate.yml +212 -0
@@ @@ -0,0 +1,212 @@
+ ---
+ http_interactions:
+ - request:
+ method: post
+ uri: http://localhost:3000/locomotive/api/v3/tokens.json?email=john@doe.net&password=asimplepassword
+ body:
+ encoding: UTF-8
+ string: ''
+ headers:
+ Accept:
+ - application/json
+ Content-Length:
+ - '0'
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 401
+ message: Unauthorized
+ headers:
+ Content-Type:
+ - application/json
+ X-Error-Detail:
+ - Invalid email or password.
+ Content-Length:
+ - '40'
+ Cache-Control:
+ - no-cache
+ X-Request-Id:
+ - fb0a7852-232e-4c8b-8ab3-456cfbab2078
+ X-Runtime:
+ - '0.664468'
+ Connection:
+ - keep-alive
+ Server:
+ - thin
+ body:
+ encoding: UTF-8
+ string: '{"message":"Invalid email or password."}'
+ http_version:
+ recorded_at: Wed, 08 Apr 2015 09:48:56 GMT
+ - request:
+ method: post
+ uri: http://localhost:3000/locomotive/api/v3/my_account.json?account%5Bemail%5D=john@doe.net&account%5Bname%5D=John&account%5Bpassword%5D=asimplepassword
+ body:
+ encoding: UTF-8
+ string: ''
+ headers:
+ Accept:
+ - application/json
+ Content-Length:
+ - '0'
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 201
+ message: Created
+ headers:
+ Content-Type:
+ - application/json
+ Content-Length:
+ - '411'
+ Etag:
+ - W/"d5f22e786ad106187b381c8d685a3e92"
+ Cache-Control:
+ - max-age=0, private, must-revalidate
+ X-Request-Id:
+ - aee412b7-82df-4978-bd1f-f8f3314ead2d
+ X-Runtime:
+ - '0.061719'
+ Connection:
+ - keep-alive
+ Server:
+ - thin
+ body:
+ encoding: UTF-8
+ string: '{"_id":"5524f98864696407ae100000","created_at":"2015-04-08T09:48:56Z","updated_at":"2015-04-08T09:48:56Z","name":"John","email":"john@doe.net","locale":"en","encrypted_password":"39f8358678144ef6715b9420a7a65706552272fb","password_salt":"sV9PWhfxDRy4b1pj6jLd","api_key":"8e5586fe34c5628d8e1ace2a8a750ae922ae2884","super_admin":false,"password":"asimplepassword","password_confirmation":null,"local_admin":false}'
+ http_version:
+ recorded_at: Wed, 08 Apr 2015 09:48:56 GMT
+ - request:
+ method: post
+ uri: http://localhost:3000/locomotive/api/v3/tokens.json?email=admin@locomotivecms.com&password=locomotive
+ body:
+ encoding: UTF-8
+ string: ''
+ headers:
+ Accept:
+ - application/json
+ Content-Length:
+ - '0'
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 201
+ message: Created
+ headers:
+ Content-Type:
+ - application/json
+ Content-Length:
+ - '32'
+ Etag:
+ - W/"333586de1d24c181814b7fd1fc093943"
+ Cache-Control:
+ - max-age=0, private, must-revalidate
+ X-Request-Id:
+ - 7b0c6596-42b7-4466-94a3-5347b7fc9234
+ X-Runtime:
+ - '0.019200'
+ Connection:
+ - keep-alive
+ Server:
+ - thin
+ body:
+ encoding: UTF-8
+ string: '{"token":"by7uUTBWyg5LzGTfyykK"}'
+ http_version:
+ recorded_at: Wed, 08 Apr 2015 10:50:39 GMT
+ - request:
+ method: get
+ uri: http://localhost:3000/locomotive/api/v3/my_account.json?auth_token=by7uUTBWyg5LzGTfyykK
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept:
+ - application/json
+ X-Locomotive-Account-Email:
+ - admin@locomotivecms.com
+ X-Locomotive-Account-Token:
+ - by7uUTBWyg5LzGTfyykK
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Content-Type:
+ - application/json
+ Content-Length:
+ - '409'
+ Etag:
+ - W/"de9362bbb5bdda2f08c588cb8bccc53e"
+ Cache-Control:
+ - max-age=0, private, must-revalidate
+ X-Request-Id:
+ - 38706597-257a-401c-9769-c8b9d27c237a
+ X-Runtime:
+ - '0.036344'
+ Connection:
+ - keep-alive
+ Server:
+ - thin
+ body:
+ encoding: UTF-8
+ string: '{"_id":"5524f99e646964184d000000","created_at":"2015-04-08T09:49:18Z","updated_at":"2015-04-08T09:49:18Z","name":"Admin","email":"admin@locomotivecms.com","locale":"en","encrypted_password":"a8f4f98e0c5a2578d750112f3df78338fa97e198","password_salt":"bQipQKDzKFhXnpXEYxoh","api_key":"d49cd50f6f0d2b163f48fc73cb249f0244c37074","super_admin":false,"password":null,"password_confirmation":null,"local_admin":true}'
+ http_version:
+ recorded_at: Wed, 08 Apr 2015 10:50:39 GMT
+ - request:
+ method: get
+ uri: http://localhost:3000/locomotive/api/v3/my_account.json?auth_token=by7uUTBWyg5LzGTfyykK
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept:
+ - application/json
+ X-Locomotive-Account-Email:
+ - admin@locomotivecms.com
+ X-Locomotive-Account-Token:
+ - by7uUTBWyg5LzGTfyykK
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ User-Agent:
+ - Ruby
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Content-Type:
+ - application/json
+ Content-Length:
+ - '409'
+ Etag:
+ - W/"de9362bbb5bdda2f08c588cb8bccc53e"
+ Cache-Control:
+ - max-age=0, private, must-revalidate
+ X-Request-Id:
+ - 92225521-e544-4a18-a1b5-7f0c45177ad0
+ X-Runtime:
+ - '0.017949'
+ Connection:
+ - keep-alive
+ Server:
+ - thin
+ body:
+ encoding: UTF-8
+ string: '{"_id":"5524f99e646964184d000000","created_at":"2015-04-08T09:49:18Z","updated_at":"2015-04-08T09:49:18Z","name":"Admin","email":"admin@locomotivecms.com","locale":"en","encrypted_password":"a8f4f98e0c5a2578d750112f3df78338fa97e198","password_salt":"bQipQKDzKFhXnpXEYxoh","api_key":"d49cd50f6f0d2b163f48fc73cb249f0244c37074","super_admin":false,"password":null,"password_confirmation":null,"local_admin":true}'
+ http_version:
+ recorded_at: Wed, 08 Apr 2015 10:50:39 GMT
+ recorded_with: VCR 2.9.3
spec/integration/commands/authenticate_command_spec.rb +43 -5
@@ @@ -2,20 +2,58 @@
require File.dirname(__FILE__) + '/../integration_helper'
require 'locomotive/wagon/commands/authenticate_command'
+ require 'thor'
describe Locomotive::Wagon::AuthenticateCommand do
- let(:platform_url) {}
- let(:email) {}
- let(:password) {}
- let(:shell) { nil }
+ before { VCR.insert_cassette 'authenticate', record: :new_episodes, match_requests_on: [:method, :query, :body] }
+ after { VCR.eject_cassette }
+
+ let(:platform_url) { TEST_PLATFORM_URL }
+ let(:shell) { Thor::Shell::Color.new }
let(:command) { described_class.new(platform_url, email, password, shell) }
describe '#authenticate' do
+ let(:netrc) { instance_double('netrc', save: true) }
+
+ before { allow(Netrc).to receive(:read).and_return(netrc) }
+
subject { command.authenticate }
- it { is_expected.to eq(true) }
+ context 'new account' do
+
+ let(:email) { 'john@doe.net' }
+ let(:password) { 'asimplepassword' }
+
+ before do
+ allow_any_instance_of(Locomotive::Coal::Resource).to receive(:api_key).and_return('42')
+ allow(Thor::LineEditor).to receive(:readline).and_return('Y', 'John')
+ end
+
+ it 'creates a new account and puts the auto-login information in the .netrc file' do
+ expect(netrc).to receive(:[]=).with('localhost:3000', ['john@doe.net', '42'])
+ is_expected.to eq(true)
+ end
+
+ end
+
+ context 'existing account' do
+
+ let(:email) { TEST_API_EMAIL }
+ let(:password) { TEST_API_PASSWORD }
+ let(:netrc) { instance_double('netrc', save: true) }
+
+ before do
+ allow_any_instance_of(Locomotive::Coal::Resource).to receive(:api_key).and_return('42')
+ end
+
+ it 'only puts the auto-login information in the .netrc file' do
+ expect(netrc).to receive(:[]=).with('localhost:3000', ['admin@locomotivecms.com', '42'])
+ is_expected.to eq(true)
+ end
+
+ end
end
spec/integration/generators/page_spec.rb +7 -7
@@ @@ -25,7 +25,7 @@ describe 'Locomotive::Wagon::Generators::Page' do
let(:locales) { '' }
- it { lambda { subject }.should_not raise_error }
+ it { expect { subject }.not_to raise_error }
end
@@ @@ -36,11 +36,11 @@ describe 'Locomotive::Wagon::Generators::Page' do
before { subject }
it 'creates the page in the FS' do
- File.exists?(page_path('new-page')).should be_true
+ expect(File).to exist(page_path('new-page'))
end
it 'generates an header in YAML' do
- read_page('new-page').should include <<-EXPECTED
+ expect(read_page('new-page')).to include <<-EXPECTED
---
title: New-page
EXPECTED
@@ @@ -51,11 +51,11 @@ EXPECTED
let(:locales) { 'en fr' }
it 'creates the EN page in the FS' do
- File.exists?(page_path('new-page')).should be_true
+ expect(File).to exist(page_path('new-page'))
end
it 'creates the FR page in the FS' do
- File.exists?(page_path('new-page.fr')).should be_true
+ expect(File).to exist(page_path('new-page.fr'))
end
describe 'separated by a comma' do
@@ @@ -63,11 +63,11 @@ EXPECTED
let(:locales) { 'en,fr' }
it 'creates the EN page in the FS' do
- File.exists?(page_path('new-page')).should be_true
+ expect(File).to exist(page_path('new-page'))
end
it 'creates the FR page in the FS' do
- File.exists?(page_path('new-page.fr')).should be_true
+ expect(File).to exist(page_path('new-page.fr'))
end
end
spec/integration/generators/relationship_spec.rb +6 -6
@@ @@ -24,7 +24,7 @@ describe 'Locomotive::Wagon::Generators::Relationship' do
let(:source_slug) { 'authors' }
- it { lambda { subject }.should raise_error 'The authors content type does not exist' }
+ it { expect { subject }.to raise_error 'The authors content type does not exist' }
end
@@ @@ -32,7 +32,7 @@ describe 'Locomotive::Wagon::Generators::Relationship' do
let(:type) { 'has_one' }
- it { lambda { subject }.should raise_error 'has_one is an unknown relationship type' }
+ it { expect { subject }.to raise_error 'has_one is an unknown relationship type' }
end
@@ @@ -43,7 +43,7 @@ describe 'Locomotive::Wagon::Generators::Relationship' do
before { subject }
it 'adds code to the source content type' do
- read_content_type(:comments).should include <<-EXPECTED
+ expect(read_content_type(:comments)).to include <<-EXPECTED
- post:
label: Post
hint: A description of the relationship for the editors
@@ @@ -53,7 +53,7 @@ EXPECTED
end
it 'adds code the target content type' do
- read_content_type(:posts).should include <<-EXPECTED
+ expect(read_content_type(:posts)).to include <<-EXPECTED
- comments:
label: Comments
hint: A description of the relationship for the editors
@@ @@ -72,7 +72,7 @@ EXPECTED
let(:type) { 'many_to_many' }
it 'adds code to the source content type' do
- read_content_type(:comments).should include <<-EXPECTED
+ expect(read_content_type(:comments)).to include <<-EXPECTED
- posts:
label: Posts
hint: A description of the relationship for the editors
@@ @@ -83,7 +83,7 @@ EXPECTED
end
it 'adds code the target content type' do
- read_content_type(:posts).should include <<-EXPECTED
+ expect(read_content_type(:posts)).to include <<-EXPECTED
- comments:
label: Comments
hint: A description of the relationship for the editors
spec/support/api_settings.rb +3 -0
@@ @@ -0,0 +1,3 @@
+ TEST_PLATFORM_URL = 'http://localhost:3000'.freeze
+ TEST_API_EMAIL = 'admin@locomotivecms.com'.freeze
+ TEST_API_PASSWORD = 'locomotive'.freeze
spec/support/pry.rb +4 -0
@@ @@ -0,0 +1,4 @@
+ begin
+ require 'pry'
+ rescue LoadError
+ end
spec/support/vcr.rb +10 -0
@@ @@ -0,0 +1,10 @@
+ require 'webmock/rspec'
+ require 'vcr'
+
+ # VCR config
+ VCR.configure do |c|
+ c.cassette_library_dir = 'spec/fixtures/cassettes'
+ c.hook_into :webmock
+ c.ignore_hosts 'codeclimate.com'
+ c.configure_rspec_metadata!
+ end
spec/unit/commands/authenticate_command_spec.rb +44 -0
@@ @@ -0,0 +1,44 @@
+ # encoding: utf-8
+
+ require 'spec_helper'
+ require 'locomotive/wagon/commands/authenticate_command'
+
+ describe Locomotive::Wagon::AuthenticateCommand do
+
+ let(:platform_url) { nil }
+ let(:email) { nil }
+ let(:password) { nil }
+ let(:shell) { nil }
+ let(:command) { described_class.new(platform_url, email, password, shell) }
+
+ describe '#api_url' do
+
+ subject { command.send(:api_url) }
+
+ context 'naked domain' do
+ let(:platform_url) { 'http://www.myengine.com:3000/' }
+ it { is_expected.to eq('http://www.myengine.com:3000/locomotive/api/v3') }
+ end
+
+ context 'localhost' do
+ let(:platform_url) { 'http://localhost:3000' }
+ it { is_expected.to eq('http://localhost:3000/locomotive/api/v3') }
+ end
+
+ context 'including the official route to the API' do
+
+ let(:platform_url) { 'http://www.myengine.com:3000/locomotive/api/v3' }
+ it { is_expected.to eq('http://www.myengine.com:3000/locomotive/api') }
+
+ end
+
+ context 'including another route to the API' do
+
+ let(:platform_url) { 'http://www.myengine.com/admin/api' }
+ it { is_expected.to eq('http://www.myengine.com/admin/api') }
+
+ end
+
+ end
+
+ end