dnsimple 2.0.0.a → 2.0.0.alpha2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +1 -2
  5. data/CHANGELOG.markdown +26 -2
  6. data/Gemfile +2 -0
  7. data/README.markdown +56 -36
  8. data/Rakefile +0 -1
  9. data/{dnsimple-ruby.gemspec → dnsimple.gemspec} +6 -4
  10. data/lib/dnsimple.rb +1 -1
  11. data/lib/dnsimple/base.rb +1 -1
  12. data/lib/dnsimple/certificate.rb +49 -35
  13. data/lib/dnsimple/client.rb +25 -72
  14. data/lib/dnsimple/contact.rb +12 -9
  15. data/lib/dnsimple/domain.rb +117 -82
  16. data/lib/dnsimple/error.rb +13 -2
  17. data/lib/dnsimple/extended_attribute.rb +3 -3
  18. data/lib/dnsimple/record.rb +9 -9
  19. data/lib/dnsimple/service.rb +3 -3
  20. data/lib/dnsimple/template.rb +8 -6
  21. data/lib/dnsimple/template_record.rb +8 -8
  22. data/lib/dnsimple/transfer_order.rb +2 -2
  23. data/lib/dnsimple/user.rb +26 -2
  24. data/lib/dnsimple/version.rb +2 -2
  25. data/spec/dnsimple/certificate_spec.rb +8 -5
  26. data/spec/dnsimple/client_spec.rb +56 -9
  27. data/spec/dnsimple/contact_spec.rb +2 -2
  28. data/spec/dnsimple/domain_spec.rb +140 -32
  29. data/spec/dnsimple/extended_attributes_spec.rb +1 -1
  30. data/spec/dnsimple/record_spec.rb +2 -2
  31. data/spec/dnsimple/template_spec.rb +1 -1
  32. data/spec/dnsimple/user_spec.rb +40 -1
  33. data/spec/files/2fa/error-badtoken.http +22 -0
  34. data/spec/files/2fa/error-required.http +23 -0
  35. data/spec/files/2fa/exchange-token.http +25 -0
  36. data/spec/files/account/user/success.http +3 -3
  37. data/spec/files/certificates/index/success.http +2 -2
  38. data/spec/files/certificates/show/notfound.http +2 -2
  39. data/spec/files/certificates/show/success.http +2 -2
  40. data/spec/files/contacts/show/notfound.http +2 -2
  41. data/spec/files/contacts/show/success.http +3 -3
  42. data/spec/files/domains/auto_renewal_disable/notfound.http +1 -1
  43. data/spec/files/domains/auto_renewal_disable/success.http +1 -1
  44. data/spec/files/domains/auto_renewal_enable/notfound.http +1 -1
  45. data/spec/files/domains/auto_renewal_enable/success.http +1 -1
  46. data/spec/files/domains/create/success.http +19 -0
  47. data/spec/files/domains/delete/success-204.http +18 -0
  48. data/spec/files/domains/delete/success.http +19 -0
  49. data/spec/files/domains/index/success.http +19 -0
  50. data/spec/files/domains/{show/notfound.http → notfound.http} +2 -2
  51. data/spec/files/domains/show/success.http +2 -2
  52. data/spec/files/extended_attributes/ca.http +2 -2
  53. data/spec/files/extended_attributes/com.http +2 -2
  54. data/spec/files/extended_attributes/success.http +2 -2
  55. data/spec/files/records/index/success.http +2 -2
  56. data/spec/files/records/show/notfound.http +2 -2
  57. data/spec/files/records/show/success.http +2 -2
  58. data/spec/files/templates/show/notfound.http +2 -2
  59. data/spec/files/templates/show/success.http +2 -2
  60. data/spec/spec_helper.rb +9 -9
  61. metadata +45 -33
  62. data/lib/dnsimple-ruby.rb +0 -1
  63. data/spec/ci/.dnsimple.test +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0418d92096c1c920c5693162451754d9bb762958
4
- data.tar.gz: 21f57179e35c105fd91708c6e4144bc55c9deafc
3
+ metadata.gz: 0e16688144a4991e78dc2f86e78dbc558c011aa4
4
+ data.tar.gz: f7dc21999ebef6b8bfee73a6a9d0afefad8ca89e
5
5
  SHA512:
6
- metadata.gz: 49dcab64cf05445a94c9b61413935e4bc03b270adcf9c676a69f261bd895d7ae96b870d7a2a38e1d38720cc0cbced0026df8d01f6d0071c538d333aa4a3171d0
7
- data.tar.gz: 183e028e671edbd2eba42b19c4e7492ec51808365f6e3a74eebe4dfd3bb72ebeb7ef8c2f52cc66c1003c821cb8a2f36f8deec2d98e6f67c0b21e20a901d43c6b
6
+ metadata.gz: 461f978e357d7a1b6895253d8c1488f7d8b720fd00b1ef80008b83071ca6d4dc8b5aafcefe927b90aacc708deda5de9fbed6f491de67ef56d0bad4d44adc087c
7
+ data.tar.gz: aef1ebfd28622173d53fc183a5834f5b42390fc3c7d4aff75686456b9d578fe5059430aab72436c55df836284bde6bde638538d524572bde220fe14e706531ee
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ Gemfile.lock
6
6
  # YARD
7
7
  .yardoc
8
8
  yardoc/
9
+ doc/
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.0
1
+ ruby-2.1
data/.travis.yml CHANGED
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.2
4
3
  - 1.9.3
5
4
  - 2.0.0
6
5
  - 2.1.0
7
- env: DNSIMPLE_TEST_CONFIG=spec/ci/.dnsimple.test
6
+ env: COVERALL=1
data/CHANGELOG.markdown CHANGED
@@ -1,8 +1,32 @@
1
1
  # Changelog
2
2
 
3
- #### Release 2.0.0
3
+ #### 2.0.0.alpha
4
4
 
5
- - NEW: Separated CLI from library. The CLI may be found at https://github.com/aetrion/dnsimple-cli
5
+ - CHANGED: Drop 1.8.7 support.
6
+
7
+ - CHANGED: This package no longer provides a CLI. The CLI has been extracted to [aetrion/dnsimple-ruby-cli](https://github.com/aetrion/dnsimple-ruby-cli)
8
+
9
+ - CHANGED: Renamed the Gem from "dnsimple-ruby" to "dnsimple". (GH-23)
10
+
11
+ - CHANGED: Renamed the namespace from DNSimple to Dnsimple.
12
+
13
+ - REMOVED: The library no longer provides built-in support for loading the credentials from a config file.
14
+
15
+ #### Release 1.7.1
16
+
17
+ - FIXED: Updated Certificate to match the serialized attributes (GH-53)
18
+
19
+ #### Release 1.7.0
20
+
21
+ - NEW: Add support for Domain-based authentication (GH-40, GH-46). Thanks @dwradcliffe and @samsonasu.
22
+
23
+ #### Release 1.6.0
24
+
25
+ - NEW: Add support for 2FA (GH-44)
26
+
27
+ #### Release 1.5.5
28
+
29
+ - NEW: Add notice about the CLI moving to a new location
6
30
 
7
31
  #### Release 1.5.4
8
32
 
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem 'coveralls', :require => false
data/README.markdown CHANGED
@@ -1,60 +1,80 @@
1
- # DNSimple Ruby API Wrapper
1
+ # DNSimple Ruby Client
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/aetrion/dnsimple-ruby.png)](http://travis-ci.org/aetrion/dnsimple-ruby)
3
+ A Ruby client for the [DNSimple API](http://developer.dnsimple.com/).
4
4
 
5
- A Ruby API wrapper for the [DNSimple API](http://developer.dnsimple.com/).
5
+ [![Build Status](https://travis-ci.org/aetrion/dnsimple-ruby.svg?branch=master)](https://travis-ci.org/aetrion/dnsimple-ruby)
6
+ [![Coverage Status](https://img.shields.io/coveralls/aetrion/dnsimple-ruby.svg)](https://coveralls.io/r/aetrion/dnsimple-ruby?branch=master)
6
7
 
7
- [DNSimple](https://dnsimple.com/) provides DNS hosting
8
- and domain registration that is simple and friendly.
8
+ [DNSimple](https://dnsimple.com/) provides DNS hosting and domain registration that is simple and friendly.
9
+ We provide a full API and an easy-to-use web interface so you can get your domain registered and set up with a minimal amount of effort.
9
10
 
10
- We provide a full API and an easy-to-use web interface so you can get
11
- your domain registered and set up with a minimal amount of effort.
12
11
 
13
12
  ## Installation
14
13
 
15
14
  $ gem install dnsimple
16
15
 
17
- ## Credentials
18
16
 
19
- Create a file in your home directory called `.dnsimple`.
17
+ ## DNSimple Client
20
18
 
21
- In this file add the following:
19
+ This library provides a Ruby DNSimple client you can use to interact with the [DNSimple API](http://developer.dnsimple.com/). Here's a short example.
22
20
 
23
- username: YOUR_USERNAME
24
- password: YOUR_PASSWORD
21
+ ```ruby
22
+ require 'dnsimple'
25
23
 
26
- Or if using an API token
24
+ DNSimple::Client.username = 'YOUR_USERNAME'
25
+ DNSimple::Client.password = 'YOUR_PASSWORD'
27
26
 
28
- username: YOUR_USERNAME
29
- api_token: YOUR_API_TOKEN
27
+ user = DNSimple::User.me
28
+ puts "#{user.domain_count} domains"
30
29
 
31
- ## Wrapper Classes
30
+ puts "Domains..."
31
+ DNSimple::Domain.all.each do |domain|
32
+ puts " #{domain.name}"
33
+ end
32
34
 
33
- In addition to the command line utility you may also use the included Ruby
34
- classes directly in your Ruby applications.
35
+ domain = DNSimple::Domain.find("example.com")
36
+ domain.apply("template") # applies a standard or custom template to the domain
35
37
 
36
- Here's a short example.
38
+ domain = DNSimple::Domain.create("newdomain.com")
39
+ puts "Added #{domain.name}"
40
+ domain.delete # removes from DNSimple
41
+ ```
37
42
 
38
- require 'rubygems'
39
- require 'dnsimple'
43
+ For the full API documentation visit http://rubydoc.info/gems/dnsimple
40
44
 
41
- DNSimple::Client.username = 'YOUR_USERNAME'
42
- DNSimple::Client.password = 'YOUR_PASSWORD'
43
- DNSimple::Client.http_proxy = {}
45
+ ### Authentication
44
46
 
45
- user = DNSimple::User.me
46
- puts "#{user.domain_count} domains"
47
+ This client supports both the HTTP Basic and API Token authentication mechanism.
47
48
 
48
- puts "Domains..."
49
- DNSimple::Domain.all.each do |domain|
50
- puts " #{domain.name}"
51
- end
49
+ #### HTTP Basic
52
50
 
53
- domain = DNSimple::Domain.find("example.com")
54
- domain.apply("template") # applies a standard or custom template to the domain
51
+ ```ruby
52
+ DNSimple::Client.username = 'YOUR_USERNAME'
53
+ DNSimple::Client.password = 'YOUR_PASSWORD'
55
54
 
56
- domain = DNSimple::Domain.create("newdomain.com")
57
- puts "Added #{domain.name}"
58
- domain.delete # removes from DNSimple
55
+ user = DNSimple::User.me
56
+ ```
59
57
 
60
- For the full API documentation visit http://rubydoc.info/gems/dnsimple-ruby
58
+ #### HTTP Basic with two-factor authentication enabled
59
+
60
+ See the [2FA API documentation](http://developer.dnsimple.com/authentication/#twofa).
61
+
62
+ ```ruby
63
+ # Request the 2FA exchange token
64
+ DNSimple::Client.username = 'YOUR_USERNAME'
65
+ DNSimple::Client.password = 'YOUR_PASSWORD'
66
+ token = DNSimple::User.two_factor_exchange_token('otp-token')
67
+
68
+ # Authenticate with the exchange token
69
+ DNSimple::Client.exchange_token = token
70
+ user = DNSimple::User.me
71
+ ```
72
+
73
+ #### API Token
74
+
75
+ ```ruby
76
+ DNSimple::Client.username = 'YOUR_USERNAME'
77
+ DNSimple::Client.api_token = 'API_TOKEN'
78
+
79
+ user = DNSimple::User.me
80
+ ```
data/Rakefile CHANGED
@@ -2,7 +2,6 @@ require 'bundler/gem_tasks'
2
2
 
3
3
  # Run test by default.
4
4
  task :default => :spec
5
- task :test => :spec
6
5
 
7
6
 
8
7
  require 'rspec/core/rake_task'
@@ -4,19 +4,21 @@ require 'dnsimple/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'dnsimple'
7
- s.version = DNSimple::VERSION
7
+ s.version = Dnsimple::VERSION
8
8
  s.authors = ['Anthony Eden', 'Simone Carletti']
9
9
  s.email = ['anthony.eden@dnsimple.com', 'simone.carletti@dnsimple.com']
10
10
  s.homepage = 'http://github.com/aetrion/dnsimple-ruby'
11
- s.summary = 'A ruby wrapper for the DNSimple API'
12
- s.description = 'A ruby wrapper for the DNSimple API.'
11
+ s.summary = 'A Ruby client for the DNSimple API'
12
+ s.description = 'A Ruby client for the DNSimple API that also includes a command-line client.'
13
+
14
+ s.required_ruby_version = ">= 1.9.3"
13
15
 
14
16
  s.require_paths = ['lib']
15
17
  s.files = `git ls-files`.split("\n")
16
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
19
  s.extra_rdoc_files = %w( README.markdown CHANGELOG.markdown LICENSE )
18
20
 
19
- s.add_dependency 'httparty', RUBY_VERSION < "1.9.3" ? [">= 0.10", "< 0.12"] : "~> 0.12"
21
+ s.add_dependency 'httparty'
20
22
 
21
23
  s.add_development_dependency 'rake'
22
24
  s.add_development_dependency 'mocha'
data/lib/dnsimple.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'httparty'
2
2
 
3
- module DNSimple
3
+ module Dnsimple
4
4
 
5
5
  BLANK_REGEX = /\S+/
6
6
 
data/lib/dnsimple/base.rb CHANGED
@@ -1,4 +1,4 @@
1
- module DNSimple
1
+ module Dnsimple
2
2
  class Base
3
3
  def initialize(attributes = {})
4
4
  attributes.each do |key, value|
@@ -1,4 +1,4 @@
1
- module DNSimple
1
+ module Dnsimple
2
2
 
3
3
  # Represents an SSL certificate that has been purchased.
4
4
  #
@@ -6,57 +6,71 @@ module DNSimple
6
6
  # before the Certificate Authority will issue a signed certificate.
7
7
  class Certificate < Base
8
8
 
9
- # The certificate ID in DNSimple
9
+ # The Fixnum certificate ID in DNSimple.
10
10
  attr_accessor :id
11
11
 
12
- attr_accessor :domain
12
+ # The Fixnum associated domain ID.
13
+ attr_accessor :domain_id
14
+
15
+ # The Fixnum associated contact ID.
16
+ attr_accessor :contact_id
13
17
 
14
- # The subdomain on the certificate
18
+ # The String subdomain on the certificate.
15
19
  attr_accessor :name
16
20
 
17
- # The Certificate Signing Request
21
+ # The String state.
22
+ attr_accessor :state
23
+
24
+ # The String Certificate Signing Request.
18
25
  attr_accessor :csr
19
26
 
20
- # The SSL certificate, if it has been issued by the Certificate Authority
27
+ # The String SSL certificate.
28
+ # It is set only if the order issued by the Certificate Authority.
21
29
  attr_accessor :ssl_certificate
22
30
 
23
- # The private key, if DNSimple generated the Certificate Signing Request
31
+ # The String private key.
32
+ # It is set only if DNSimple generated the Certificate Signing Request.
24
33
  attr_accessor :private_key
25
34
 
26
- # The approver email address
35
+ # The String approver email address
36
+ # It is set only if the state is submitted.
27
37
  attr_accessor :approver_email
28
38
 
29
- # When the certificate was purchased
39
+ # The Array of all emails that can be used to approve the certificate.
40
+ # It is set only if the state is configured.
41
+ attr_accessor :approver_emails
42
+
43
+ # The Date the certificate was create in DNSimple.
30
44
  attr_accessor :created_at
31
45
 
32
- # When the certificate was last updated
46
+ # The Date the certificate was last updated in DNSimple.
33
47
  attr_accessor :updated_at
34
48
 
35
- # An array of all emails that can be used to approve the certificate
36
- attr_accessor :available_approver_emails
37
-
38
- # The Certificate status
39
- attr_accessor :certificate_status
49
+ # The Date the certificate was configured.
50
+ attr_accessor :configured_at
40
51
 
41
- # The date the Certificate order was placed
42
- attr_accessor :order_date
52
+ # The Date the certificate will expire.
53
+ attr_accessor :expires_on
43
54
 
44
- # The date the Certificate will expire
45
- attr_accessor :expiration_date
55
+ # The associated Domain.
56
+ attr_accessor :domain
46
57
 
47
58
 
48
- # Purchase a certificate under the given domain with the given name. The
49
- # name will be appended to the domain name, and thus should only be the
50
- # subdomain part.
59
+ # Purchases a certificate under the given domain with the given name.
51
60
  #
52
- # Example: DNSimple::Certificate.purchase(domain, 'www', contact)
61
+ # The name will be appended to the domain name, and thus should only be the subdomain part.
53
62
  #
54
- # Please note that by invoking this method DNSimple will immediately charge
63
+ # Invoking this method DNSimple will immediately charge
55
64
  # your credit card on file at DNSimple for the full certificate price.
56
65
  #
57
66
  # For wildcard certificates an asterisk must appear in the name.
58
67
  #
59
- # Example: DNSimple::Certificate.purchase(domain, '*', contact)
68
+ # @example Purchase a single-hostname certificate
69
+ # Dnsimple::Certificate.purchase(domain, 'www', contact)
70
+ #
71
+ # @example Purchase a wildcard certificate
72
+ # Dnsimple::Certificate.purchase(domain, '*', contact)
73
+ #
60
74
  def self.purchase(domain, name, contact, options={})
61
75
  certificate_hash = {
62
76
  :name => name,
@@ -65,7 +79,7 @@ module DNSimple
65
79
 
66
80
  options.merge!({:body => {:certificate => certificate_hash}})
67
81
 
68
- response = DNSimple::Client.post("/v1/domains/#{domain.name}/certificates", options)
82
+ response = Client.post("/v1/domains/#{domain.name}/certificates", options)
69
83
 
70
84
  case response.code
71
85
  when 201
@@ -79,7 +93,7 @@ module DNSimple
79
93
 
80
94
  # Get an array of all certificates for the given domain.
81
95
  def self.all(domain, options={})
82
- response = DNSimple::Client.get("/v1/domains/#{domain.name}/certificates", options)
96
+ response = Client.get("/v1/domains/#{domain.name}/certificates", options)
83
97
 
84
98
  case response.code
85
99
  when 200
@@ -91,7 +105,7 @@ module DNSimple
91
105
 
92
106
  # Find a specific certificate for the given domain.
93
107
  def self.find(domain, id, options = {})
94
- response = DNSimple::Client.get("/v1/domains/#{domain.name}/certificates/#{id}", options)
108
+ response = Client.get("/v1/domains/#{domain.name}/certificates/#{id}", options)
95
109
 
96
110
  case response.code
97
111
  when 200
@@ -107,21 +121,21 @@ module DNSimple
107
121
  # Get the fully-qualified domain name for the certificate. This is the
108
122
  # domain.name joined with the certificate name, separated by a period.
109
123
  def fqdn
110
- [name, domain.name].delete_if { |p| p !~ DNSimple::BLANK_REGEX }.join(".")
124
+ [name, domain.name].delete_if { |p| p !~ BLANK_REGEX }.join(".")
111
125
  end
112
126
 
113
127
  def submit(approver_email, options={})
114
- raise DNSimple::Error, "Approver email is required" unless approver_email
128
+ raise Error, "Approver email is required" unless approver_email
115
129
 
116
130
  options.merge!(:body => {:certificate => {:approver_email => approver_email}})
117
131
 
118
- response = DNSimple::Client.put("/v1/domains/#{domain.name}/certificates/#{id}/submit", options)
132
+ response = Client.put("/v1/domains/#{domain.name}/certificates/#{id}/submit", options)
119
133
 
120
134
  case response.code
121
- when 200
122
- Certificate.new({ :domain => domain }.merge(response["certificate"]))
123
- else
124
- raise RequestError.new("Error submitting certificate", response)
135
+ when 200
136
+ Certificate.new({ :domain => domain }.merge(response["certificate"]))
137
+ else
138
+ raise RequestError.new("Error submitting certificate", response)
125
139
  end
126
140
  end
127
141
 
@@ -1,42 +1,22 @@
1
1
  require 'dnsimple/version'
2
2
  require 'yaml'
3
3
 
4
- module DNSimple
4
+ module Dnsimple
5
5
  class Client
6
6
 
7
- DEFAULT_BASE_URI = "https://api.dnsimple.com/"
7
+ DEFAULT_BASE_URI = "https://api.dnsimple.com/"
8
+ HEADER_2FA_STRICT = "X-DNSimple-2FA-Strict"
9
+ HEADER_API_TOKEN = "X-DNSimple-Token"
10
+ HEADER_DOMAIN_API_TOKEN = "X-DNSimple-Domain-Token"
11
+ HEADER_OTP_TOKEN = "X-DNSimple-OTP"
12
+ HEADER_EXCHANGE_TOKEN = "X-DNSimple-OTP-Token"
8
13
 
14
+ class << self
15
+ # @return [Boolean] if the debug mode is enabled.
16
+ # Defaults to false.
17
+ attr_accessor :debug
9
18
 
10
- def self.debug?
11
- @debug
12
- end
13
-
14
- def self.debug=(debug)
15
- @debug = debug
16
- end
17
-
18
- def self.username
19
- @username
20
- end
21
-
22
- def self.username=(username)
23
- @username = username
24
- end
25
-
26
- def self.password
27
- @password
28
- end
29
-
30
- def self.password=(password)
31
- @password = password
32
- end
33
-
34
- def self.api_token
35
- @api_token
36
- end
37
-
38
- def self.api_token=(api_token)
39
- @api_token = api_token
19
+ attr_accessor :username, :password, :exchange_token, :api_token, :domain_api_token
40
20
  end
41
21
 
42
22
  # Gets the qualified API base uri.
@@ -57,56 +37,27 @@ module DNSimple
57
37
  @http_proxy
58
38
  end
59
39
 
60
- def self.http_proxy=(http_proxy)
61
- @http_proxy = http_proxy
62
- end
63
-
64
- def self.load_credentials_if_necessary
65
- load_credentials unless credentials_loaded?
66
- end
67
-
68
- def self.config_path
69
- ENV['DNSIMPLE_CONFIG'] || '~/.dnsimple'
70
- end
71
-
72
- def self.load_credentials(path = config_path)
73
- begin
74
- credentials = YAML.load_file(File.expand_path(path))
75
- self.username ||= credentials['username']
76
- self.password ||= credentials['password']
77
- self.api_token ||= credentials['api_token']
78
- self.base_uri = credentials['site'] if credentials['site']
79
- self.base_uri = credentials['base_uri'] if credentials['base_uri']
80
- self.http_proxy = { :addr => credentials['proxy_addr'], :port => credentials['proxy_port'] } if credentials['proxy_addr'] || credentials['proxy_port']
81
- @credentials_loaded = true
82
- puts "Credentials loaded from #{path}"
83
- rescue => error
84
- puts "Error loading your credentials: #{error.message}"
85
- exit 1
86
- end
87
- end
88
-
89
- def self.credentials_loaded?
90
- (@credentials_loaded ||= false) or (username and (password or api_token))
91
- end
92
-
93
40
  def self.base_options
94
41
  options = {
95
42
  :format => :json,
96
- :headers => { 'Accept' => 'application/json', 'User-Agent' => "dnsimple-ruby/#{DNSimple::VERSION}" },
43
+ :headers => { 'Accept' => 'application/json', 'User-Agent' => "dnsimple-ruby/#{VERSION}" },
97
44
  }
98
45
 
99
46
  if http_proxy
100
47
  options.merge!(
101
- :http_proxyaddr => self.http_proxy[:addr],
102
- :http_proxyport => self.http_proxy[:port]
48
+ :http_proxyaddr => http_proxy[:addr],
49
+ :http_proxyport => http_proxy[:port]
103
50
  )
104
51
  end
105
52
 
106
- if password
53
+ if exchange_token
54
+ options[:basic_auth] = { :username => exchange_token, :password => "x-2fa-basic" }
55
+ elsif password
107
56
  options[:basic_auth] = { :username => username, :password => password }
57
+ elsif domain_api_token
58
+ options[:headers][HEADER_DOMAIN_API_TOKEN] = domain_api_token
108
59
  elsif api_token
109
- options[:headers]['X-DNSimple-Token'] = "#{username}:#{api_token}"
60
+ options[:headers][HEADER_API_TOKEN] = "#{username}:#{api_token}"
110
61
  else
111
62
  raise Error, 'A password or API token is required for all API requests.'
112
63
  end
@@ -133,8 +84,10 @@ module DNSimple
133
84
  def self.request(method, path, options)
134
85
  response = HTTParty.send(method, "#{base_uri}#{path}", base_options.merge(options))
135
86
 
136
- if response.code == 401
137
- raise AuthenticationFailed
87
+ if response.code == 401 && response.headers[HEADER_OTP_TOKEN] == "required"
88
+ raise TwoFactorAuthenticationRequired, response["message"]
89
+ elsif response.code == 401
90
+ raise AuthenticationFailed, response["message"]
138
91
  end
139
92
 
140
93
  response