Skip to content

Commit

Permalink
Merge 5d3e545 into c1e30f6
Browse files Browse the repository at this point in the history
  • Loading branch information
jacegu committed Dec 14, 2015
2 parents c1e30f6 + 5d3e545 commit e69b1f6
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 44 deletions.
29 changes: 13 additions & 16 deletions lib/dnsimple/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ class Client
include Dnsimple::Compatibility

HEADER_2FA_STRICT = "X-DNSimple-2FA-Strict"
HEADER_API_TOKEN = "X-DNSimple-Token"
HEADER_DOMAIN_API_TOKEN = "X-DNSimple-Domain-Token"
HEADER_OTP_TOKEN = "X-DNSimple-OTP"
HEADER_EXCHANGE_TOKEN = "X-DNSimple-OTP-Token"
HEADER_OAUTH_ACCESS_TOKEN = "Authorization"


# @return [String] The current API version.
Expand All @@ -36,22 +35,22 @@ def self.versioned(path)
# @!attribute password
# @see http://developer.dnsimple.com/authentication/
# @return [String] DNSimple password for Basic Authentication
# @!attribute exchange_token
# @see http://developer.dnsimple.com/authentication/
# @return [String] Exchange Token for Basic Authentication with 2FA
# @!attribute api_token
# @see http://developer.dnsimple.com/authentication/
# @return [String] API access token for authentication
# @!attribute domain_api_token
# @see http://developer.dnsimple.com/authentication/
# @return [String] Domain API access token for authentication
# @!attribute oauth_client_id
# @see http://developer.dnsimple.com/authentication/
# @return [String] OAuth client id for authentication
# @!attribute oauth_client_secret
# @see http://developer.dnsimple.com/authentication/
# @return [String] OAuth client secret for authentication
# @!attribute user_agent
# @return [String] Configure User-Agent header for requests.
# @!attribute proxy
# @return [String,nil] Configure address:port values for proxy server

attr_accessor :api_endpoint, :username, :password, :exchange_token, :api_token, :domain_api_token,
:user_agent, :proxy
attr_accessor :api_endpoint, :username, :password, :domain_api_token, :oauth_access_token,
:oauth_client_id, :oauth_client_secret, :user_agent, :proxy


def initialize(options = {})
Expand Down Expand Up @@ -172,16 +171,14 @@ def base_options
options.merge!(http_proxyaddr: address, http_proxyport: port)
end

if exchange_token
options[:basic_auth] = { username: exchange_token, password: "x-2fa-basic" }
elsif password
if password
options[:basic_auth] = { username: username, password: password }
elsif domain_api_token
options[:headers][HEADER_DOMAIN_API_TOKEN] = domain_api_token
elsif api_token
options[:headers][HEADER_API_TOKEN] = "#{username}:#{api_token}"
elsif oauth_access_token
options[:headers][HEADER_OAUTH_ACCESS_TOKEN] = "Bearer #{oauth_access_token}"
else
raise Error, 'A password or API token is required for all API requests.'
raise Error, 'A password, domain API token or OAuth access token is required for all API requests.'
end

options
Expand Down
2 changes: 1 addition & 1 deletion lib/dnsimple/compatibility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ def delete(*args)

end

end
end
31 changes: 19 additions & 12 deletions lib/dnsimple/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ def keys
:api_endpoint,
:username,
:password,
:exchange_token,
:api_token,
:domain_api_token,
:oauth_access_token,
:oauth_client_id,
:oauth_client_secret,
:user_agent,
:proxy,
]
Expand Down Expand Up @@ -50,22 +51,28 @@ def password
ENV['DNSIMPLE_PASSWORD']
end

# Default DNSimple Exchange Token for Basic Auth from ENV
# @return [String]
def exchange_token
ENV['DNSIMPLE_API_EXCHANGE_TOKEN']
end

# Default DNSimple Domain API Token for Token Auth from ENV
# @return [String]
def domain_api_token
ENV['DNSIMPLE_API_DOMAIN_TOKEN']
end

# Default DNSimple API Token for Token Auth from ENV
# Default DNSimple OAuth access token for OAuth authentication from ENV
# @return [String]
def oauth_access_token
ENV['DNSIMPLE_OAUTH_ACCESS_TOKEN']
end

# Default DNSimple OAuth client ID for OAuth authentication from ENV
# @return [String]
def oauth_client_id
ENV['DNSIMPLE_OAUTH_CLIENT_ID']
end

# Default DNSimple OAuth client secret for OAuth authentication from ENV
# @return [String]
def api_token
ENV['DNSIMPLE_API_TOKEN']
def oauth_client_secret
ENV['DNSIMPLE_OAUTH_CLIENT_SECRET']
end

# Default User-Agent header string from ENV or {USER_AGENT}
Expand All @@ -83,4 +90,4 @@ def proxy
end
end

end
end
32 changes: 17 additions & 15 deletions spec/dnsimple/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
expect(subject.api_endpoint).to eq("https://api.example.com/")
end

it "accepts :oauth_client_id and :oauth_client_secret options" do
subject = described_class.new(oauth_client_id: "id", oauth_client_secret: "secret")
expect(subject.oauth_client_id).to eq("id")
expect(subject.oauth_client_secret).to eq("secret")
end

it "access :oauth_access_token option" do
subject = described_class.new(oauth_access_token: "token")
expect(subject.oauth_access_token).to eq("token")
end

it "normalizes :api_endpoint trailing slash" do
subject = described_class.new(api_endpoint: "https://api.example.com/missing/slash")
expect(subject.api_endpoint).to eq("https://api.example.com/missing/slash/")
Expand Down Expand Up @@ -39,31 +50,22 @@
with { |req| req.headers["X-Dnsimple-Domain-Token"] == "domaintoken" }
end

it "uses header authentication if there's an api token provided" do
it "uses OAuth access token if there's an access token provided" do
stub_request(:any, %r[/test])

subject = described_class.new(username: "user", api_token: "token")
subject = described_class.new(oauth_access_token: "access-token")
subject.execute(:get, "test", {})

expect(WebMock).to have_requested(:get, "https://api.dnsimple.com/test").
with { |req| req.headers["X-Dnsimple-Token"] == "user:token" }
end

it "uses HTTP authentication via exchange token if there's an exchange token provided" do
stub_request(:any, %r[/test])

subject = described_class.new(username: "user", password: "pass", exchange_token: "exchange-token")
subject.execute(:get, "test", {})

expect(WebMock).to have_requested(:get, "https://exchange-token:x-2fa-basic@api.dnsimple.com/test")
with { |req| req.headers["Authorization"] == "Bearer access-token" }
end

it "raises an error if there's no password or api token provided" do
subject = described_class.new(username: "user")
it "raises an error if there's no password, domain token or access token provided" do
subject = described_class.new(username: "user", oauth_client_id: "id", oauth_client_secret: "secret")

expect {
subject.execute(:get, "test", {})
}.to raise_error(Dnsimple::Error, 'A password or API token is required for all API requests.')
}.to raise_error(Dnsimple::Error, "A password, domain API token or OAuth access token is required for all API requests.")
end

context "when 2FA is required" do
Expand Down

0 comments on commit e69b1f6

Please sign in to comment.