diff --git a/lib/dnsimple/client.rb b/lib/dnsimple/client.rb index 397347a2..bbe24bc8 100644 --- a/lib/dnsimple/client.rb +++ b/lib/dnsimple/client.rb @@ -71,58 +71,63 @@ def base_url # Make a HTTP GET request. # # @param [String] path The path, relative to {#base_url} - # @param [Hash] options Query and header params for request + # @param [Hash] options The query and header params for the request # @return [HTTParty::Response] def get(path, options = {}) - execute :get, path, options + execute :get, path, nil, options end # Make a HTTP POST request. # # @param [String] path The path, relative to {#base_url} - # @param [Hash] options Body and header params for request + # @param [Hash] data The body for the request + # @param [Hash] options The query and header params for the request # @return [HTTParty::Response] - def post(path, options = {}) - execute :post, path, options + def post(path, data = nil, options= {}) + execute :post, path, data, options end # Make a HTTP PUT request. # # @param [String] path The path, relative to {#base_url} - # @param [Hash] options Body and header params for request + # @param [Hash] data The body for the request + # @param [Hash] options The query and header params for the request # @return [HTTParty::Response] - def put(path, options = {}) - execute :put, path, options + def put(path, data = nil, options = {}) + execute :put, path, data, options end # Make a HTTP PATCH request. # # @param [String] path The path, relative to {#base_url} - # @param [Hash] options Body and header params for request + # @param [Hash] data The body for the request + # @param [Hash] options The query and header params for the request # @return [HTTParty::Response] - def patch(path, options = {}) - execute :patch, path, options + def patch(path, data = nil, options = {}) + execute :patch, path, data, options end # Make a HTTP DELETE request. # # @param [String] path The path, relative to {#base_url} - # @param [Hash] options Query and header params for request + # @param [Hash] options The query and header params for the request # @return [HTTParty::Response] - def delete(path, options = {}) - execute :delete, path, options + def delete(path, data = nil, options = {}) + execute :delete, path, data, options end # Executes a request, validates and returns the response. # # @param [String] method The HTTP method # @param [String] path The path, relative to {#base_url} - # @param [Hash] options Query and header params for request + # @param [Hash] data The body for the request + # @param [Hash] options The query and header params for the request # @return [HTTParty::Response] # @raise [RequestError] # @raise [NotFoundError] # @raise [AuthenticationFailed] - def execute(method, path, data, options = {}) + # @raise [TwoFactorAuthenticationRequired] + def execute(method, path, data = nil, options = {}) response = request(method, path, data, options) case response.code @@ -147,16 +152,11 @@ def execute(method, path, data, options = {}) # # @param [String] method The HTTP method # @param [String] path The path, relative to {#base_url} - # @param [Hash] options Query and header params for request + # @param [Hash] data The body for the request + # @param [Hash] options The query and header params for the request # @return [HTTParty::Response] - def request(method, path, data, options = {}) - if data.is_a?(Hash) - options[:query] = data.delete(:query) if data.key?(:query) - options[:headers] = data.delete(:headers) if data.key?(:headers) - end - if !data.empty? - options[:body] = data - end + def request(method, path, data = nil, options = {}) + options[:body] = data if data HTTParty.send(method, base_url + path, Extra.deep_merge!(base_options, options)) end diff --git a/lib/dnsimple/client/contacts.rb b/lib/dnsimple/client/contacts.rb index 399ab5f9..9e4d3bad 100644 --- a/lib/dnsimple/client/contacts.rb +++ b/lib/dnsimple/client/contacts.rb @@ -57,10 +57,9 @@ def all_contacts(account_id, options = {}) # @return [Dnsimple::Response] # # @raise [Dnsimple::RequestError] - def create_contact(account_id, attributes = {}, options = {}) + def create_contact(account_id, attributes, options = {}) Extra.validate_mandatory_attributes(attributes, [:first_name, :last_name, :address1, :city, :state_province, :postal_code, :country, :phone, :email_address]) - options = options.merge(attributes) - response = client.post(Client.versioned("/%s/contacts" % [account_id]), options) + response = client.post(Client.versioned("/%s/contacts" % [account_id]), attributes, options) Dnsimple::Response.new(response, Struct::Contact.new(response["data"])) end @@ -94,9 +93,8 @@ def contact(account_id, contact_id, options = {}) # @return [Dnsimple::Response] # # @raise [Dnsimple::RequestError] - def update_contact(account_id, contact_id, attributes = {}, options = {}) - options = options.merge(attributes) - response = client.patch(Client.versioned("/%s/contacts/%s" % [account_id, contact_id]), options) + def update_contact(account_id, contact_id, attributes, options = {}) + response = client.patch(Client.versioned("/%s/contacts/%s" % [account_id, contact_id]), attributes, options) Dnsimple::Response.new(response, Struct::Contact.new(response["data"])) end @@ -116,7 +114,7 @@ def update_contact(account_id, contact_id, attributes = {}, options = {}) # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def delete_contact(account_id, contact_id, options = {}) - response = client.delete(Client.versioned("/%s/contacts/%s" % [account_id, contact_id]), options) + response = client.delete(Client.versioned("/%s/contacts/%s" % [account_id, contact_id]), nil, options) Dnsimple::Response.new(response, nil) end diff --git a/lib/dnsimple/client/domains.rb b/lib/dnsimple/client/domains.rb index e90a62f6..e9e8a0b9 100644 --- a/lib/dnsimple/client/domains.rb +++ b/lib/dnsimple/client/domains.rb @@ -57,10 +57,10 @@ def all_domains(account_id, options = {}) # @return [Dnsimple::Response] # # @raise [Dnsimple::RequestError] - def create_domain(account_id, attributes = {}, options = {}) + def create_domain(account_id, attributes, options = {}) Extra.validate_mandatory_attributes(attributes, [:name]) options = options.merge(attributes) - response = client.post(Client.versioned("/%s/domains" % [account_id]), options) + response = client.post(Client.versioned("/%s/domains" % [account_id]), attributes, options) Dnsimple::Response.new(response, Struct::Domain.new(response["data"])) end @@ -97,7 +97,7 @@ def domain(account_id, domain_id, options = {}) # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def delete_domain(account_id, domain_id, options = {}) - response = client.delete(Client.versioned("/%s/domains/%s" % [account_id, domain_id]), options) + response = client.delete(Client.versioned("/%s/domains/%s" % [account_id, domain_id]), nil, options) Dnsimple::Response.new(response, nil) end @@ -115,7 +115,7 @@ def delete_domain(account_id, domain_id, options = {}) # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def reset_domain_token(account_id, domain_id, options = {}) - response = client.post(Client.versioned("/%s/domains/%s/token" % [account_id, domain_id]), options) + response = client.post(Client.versioned("/%s/domains/%s/token" % [account_id, domain_id]), nil, options) Dnsimple::Response.new(response, Struct::Domain.new(response["data"])) end diff --git a/lib/dnsimple/client/domains_email_forwards.rb b/lib/dnsimple/client/domains_email_forwards.rb index 46a8a875..196c9f87 100644 --- a/lib/dnsimple/client/domains_email_forwards.rb +++ b/lib/dnsimple/client/domains_email_forwards.rb @@ -57,10 +57,9 @@ def all_email_forwards(account_id, domain_id, options = {}) # @return [Dnsimple::Response] # # @raise [Dnsimple::RequestError] - def create_email_forward(account_id, domain_id, attributes = {}, options = {}) + def create_email_forward(account_id, domain_id, attributes, options = {}) Extra.validate_mandatory_attributes(attributes, [:from, :to]) - options = options.merge(attributes) - response = client.post(Client.versioned("/%s/domains/%s/email_forwards" % [account_id, domain_id]), options) + response = client.post(Client.versioned("/%s/domains/%s/email_forwards" % [account_id, domain_id]), attributes, options) Dnsimple::Response.new(response, Struct::EmailForward.new(response["data"])) end @@ -98,7 +97,7 @@ def email_forward(account_id, domain_id, email_forward_id, options = {}) # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def delete_email_forward(account_id, domain_id, email_forward_id, options = {}) - response = client.delete(Client.versioned("/%s/domains/%s/email_forwards/%s" % [account_id, domain_id, email_forward_id]), options) + response = client.delete(Client.versioned("/%s/domains/%s/email_forwards/%s" % [account_id, domain_id, email_forward_id]), nil, options) Dnsimple::Response.new(response, nil) end diff --git a/lib/dnsimple/client/oauth.rb b/lib/dnsimple/client/oauth.rb index 4181de2b..62087b0a 100644 --- a/lib/dnsimple/client/oauth.rb +++ b/lib/dnsimple/client/oauth.rb @@ -12,8 +12,8 @@ module Oauth # @option options [String] :redirect_uri The redirect URL sent for the authorization, used to validate the request. # @return [String] The url to redirect the user to authorize. def exchange_authorization_for_token(code, client_id, client_secret, options = {}) - options = options.merge({ code: code, client_id: client_id, client_secret: client_secret, grant_type: "authorization_code" }) - response = client.post(Client.versioned("/oauth/access_token"), options) + attributes = { code: code, client_id: client_id, client_secret: client_secret, grant_type: "authorization_code" } + response = client.post(Client.versioned("/oauth/access_token"), attributes, options) Struct::OauthToken.new(response) end @@ -39,4 +39,4 @@ def authorize_url(client_id, options = {}) end end -end \ No newline at end of file +end diff --git a/lib/dnsimple/client/registrar.rb b/lib/dnsimple/client/registrar.rb index 89400327..8a180084 100644 --- a/lib/dnsimple/client/registrar.rb +++ b/lib/dnsimple/client/registrar.rb @@ -37,10 +37,10 @@ def check_domain(account_id, domain_name, options = {}) # @return [Struct::Domain] # # @raise [RequestError] When the request fails. - def register_domain(account_id, domain_name, attributes = {}, options = {}) + def register_domain(account_id, domain_name, attributes, options = {}) Extra.validate_mandatory_attributes(attributes, [:registrant_id]) endpoint = Client.versioned("/%s/registrar/domains/%s/registration" % [account_id, domain_name]) - response = client.post(endpoint, options.merge(attributes)) + response = client.post(endpoint, attributes, options) Dnsimple::Response.new(response, Struct::Domain.new(response["data"])) end @@ -59,9 +59,9 @@ def register_domain(account_id, domain_name, attributes = {}, options = {}) # @return [Struct::Domain] # # @raise [RequestError] When the request fails. - def renew_domain(account_id, domain_name, attributes = {}, options = {}) + def renew_domain(account_id, domain_name, attributes = nil, options = {}) endpoint = Client.versioned("/%s/registrar/domains/%s/renew" % [account_id, domain_name]) - response = client.post(endpoint, options.merge(attributes)) + response = client.post(endpoint, attributes, options) Dnsimple::Response.new(response, Struct::Domain.new(response["data"])) end @@ -80,10 +80,10 @@ def renew_domain(account_id, domain_name, attributes = {}, options = {}) # @return [Struct::Domain] # # @raise [RequestError] When the request fails. - def transfer_domain(account_id, domain_name, attributes = {}, options = {}) + def transfer_domain(account_id, domain_name, attributes, options = {}) Extra.validate_mandatory_attributes(attributes, [:registrant_id]) endpoint = Client.versioned("/%s/registrar/domains/%s/transfer" % [account_id, domain_name]) - response = client.post(endpoint, options.merge(attributes)) + response = client.post(endpoint, attributes, options) Dnsimple::Response.new(response, Struct::Domain.new(response["data"])) end @@ -103,7 +103,7 @@ def transfer_domain(account_id, domain_name, attributes = {}, options = {}) # @raise [RequestError] When the request fails. def transfer_domain_out(account_id, domain_name, options = {}) endpoint = Client.versioned("/%s/registrar/domains/%s/transfer_out" % [account_id, domain_name]) - response = client.post(endpoint, options) + response = client.post(endpoint, nil, options) Dnsimple::Response.new(response, nil) end diff --git a/lib/dnsimple/client/registrar_auto_renewal.rb b/lib/dnsimple/client/registrar_auto_renewal.rb index 41ef07ae..550e0ca4 100644 --- a/lib/dnsimple/client/registrar_auto_renewal.rb +++ b/lib/dnsimple/client/registrar_auto_renewal.rb @@ -14,7 +14,7 @@ module RegistrarAutoRenewal # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def enable_auto_renewal(account_id, domain_name, options={}) - response = client.put(Client.versioned("/%s/registrar/domains/%s/auto_renewal" % [account_id, domain_name]), options) + response = client.put(Client.versioned("/%s/registrar/domains/%s/auto_renewal" % [account_id, domain_name]), nil, options) Dnsimple::Response.new(response, nil) end @@ -31,7 +31,7 @@ def enable_auto_renewal(account_id, domain_name, options={}) # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def disable_auto_renewal(account_id, domain_name, options={}) - response = client.delete(Client.versioned("/%s/registrar/domains/%s/auto_renewal" % [account_id, domain_name]), options) + response = client.delete(Client.versioned("/%s/registrar/domains/%s/auto_renewal" % [account_id, domain_name]), nil, options) Dnsimple::Response.new(response, nil) end diff --git a/lib/dnsimple/client/registrar_whois_privacy.rb b/lib/dnsimple/client/registrar_whois_privacy.rb index e04766d2..2d3d6272 100644 --- a/lib/dnsimple/client/registrar_whois_privacy.rb +++ b/lib/dnsimple/client/registrar_whois_privacy.rb @@ -37,7 +37,7 @@ def whois_privacy(account_id, domain_name, options = {}) # @raise [RequestError] When the request fails. def enable_whois_privacy(account_id, domain_name, options = {}) endpoint = whois_privacy_endpoint(account_id, domain_name) - response = client.put(endpoint, options) + response = client.put(endpoint, nil, options) Dnsimple::Response.new(response, Struct::WhoisPrivacy.new(response["data"])) end @@ -57,7 +57,7 @@ def enable_whois_privacy(account_id, domain_name, options = {}) # @raise [RequestError] When the request fails. def disable_whois_privacy(account_id, domain_name, options = {}) endpoint = whois_privacy_endpoint(account_id, domain_name) - response = client.delete(endpoint, options) + response = client.delete(endpoint, nil, options) Dnsimple::Response.new(response, Struct::WhoisPrivacy.new(response["data"])) end diff --git a/lib/dnsimple/client/webhooks.rb b/lib/dnsimple/client/webhooks.rb index 36382ee2..fb776822 100644 --- a/lib/dnsimple/client/webhooks.rb +++ b/lib/dnsimple/client/webhooks.rb @@ -32,10 +32,9 @@ def webhooks(account_id, options = {}) # @return [Dnsimple::Response] # # @raise [Dnsimple::RequestError] - def create_webhook(account_id, attributes = {}, options = {}) + def create_webhook(account_id, attributes, options = {}) Extra.validate_mandatory_attributes(attributes, [:url]) - options = options.merge(attributes) - response = client.post(Client.versioned("/%s/webhooks" % [account_id]), options) + response = client.post(Client.versioned("/%s/webhooks" % [account_id]), attributes, options) Dnsimple::Response.new(response, Struct::Webhook.new(response["data"])) end @@ -72,7 +71,7 @@ def webhook(account_id, webhook_id, options = {}) # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def delete_webhook(account_id, webhook_id, options = {}) - response = client.delete(Client.versioned("/%s/webhooks/%s" % [account_id, webhook_id]), options) + response = client.delete(Client.versioned("/%s/webhooks/%s" % [account_id, webhook_id]), nil, options) Dnsimple::Response.new(response, nil) end diff --git a/lib/dnsimple/client/zones_records.rb b/lib/dnsimple/client/zones_records.rb index 89b692b1..e387629e 100644 --- a/lib/dnsimple/client/zones_records.rb +++ b/lib/dnsimple/client/zones_records.rb @@ -58,10 +58,9 @@ def all_records(account_id, zone_id, options = {}) # @return [Dnsimple::Response] # # @raise [Dnsimple::RequestError] - def create_record(account_id, zone_id, attributes = {}, options = {}) + def create_record(account_id, zone_id, attributes, options = {}) Extra.validate_mandatory_attributes(attributes, [:type, :name, :content]) - options = options.merge(attributes) - response = client.post(Client.versioned("/%s/zones/%s/records" % [account_id, zone_id]), options) + response = client.post(Client.versioned("/%s/zones/%s/records" % [account_id, zone_id]), attributes, options) Dnsimple::Response.new(response, Struct::Record.new(response["data"])) end @@ -97,9 +96,8 @@ def record(account_id, zone_id, record_id, options = {}) # # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] - def update_record(account_id, zone_id, record_id, attributes = {}, options = {}) - options = options.merge(attributes) - response = client.patch(Client.versioned("/%s/zones/%s/records/%s" % [account_id, zone_id, record_id]), options) + def update_record(account_id, zone_id, record_id, attributes, options = {}) + response = client.patch(Client.versioned("/%s/zones/%s/records/%s" % [account_id, zone_id, record_id]), attributes, options) Dnsimple::Response.new(response, Struct::Record.new(response["data"])) end @@ -119,7 +117,7 @@ def update_record(account_id, zone_id, record_id, attributes = {}, options = {}) # @raise [Dnsimple::NotFoundError] # @raise [Dnsimple::RequestError] def delete_record(account_id, zone_id, record_id, options = {}) - response = client.delete(Client.versioned("/%s/zones/%s/records/%s" % [account_id, zone_id, record_id]), options) + response = client.delete(Client.versioned("/%s/zones/%s/records/%s" % [account_id, zone_id, record_id]), nil, options) Dnsimple::Response.new(response, nil) end diff --git a/lib/dnsimple/extra.rb b/lib/dnsimple/extra.rb index 6d67fdd8..cf69a826 100644 --- a/lib/dnsimple/extra.rb +++ b/lib/dnsimple/extra.rb @@ -53,7 +53,7 @@ def self.deep_merge!(this, other, &block) # @raise [ArgumentError] def self.validate_mandatory_attributes(attributes, required) required.each do |name| - attributes.key?(name) or raise(ArgumentError, ":#{name} is required") + attributes && attributes.key?(name) or raise(ArgumentError, ":#{name} is required") end end diff --git a/spec/dnsimple/client/contacts_spec.rb b/spec/dnsimple/client/contacts_spec.rb index c28b3b71..d93f504c 100644 --- a/spec/dnsimple/client/contacts_spec.rb +++ b/spec/dnsimple/client/contacts_spec.rb @@ -151,7 +151,7 @@ end it "returns the contact" do - response = subject.update_contact(account_id, 1) + response = subject.update_contact(account_id, 1, attributes) expect(response).to be_a(Dnsimple::Response) result = response.data diff --git a/spec/dnsimple/client/zones_records_spec.rb b/spec/dnsimple/client/zones_records_spec.rb index f55b46c9..5efac134 100644 --- a/spec/dnsimple/client/zones_records_spec.rb +++ b/spec/dnsimple/client/zones_records_spec.rb @@ -196,7 +196,7 @@ end it "returns the record" do - response = subject.update_record(account_id, zone_id, 2) + response = subject.update_record(account_id, zone_id, 2, attributes) expect(response).to be_a(Dnsimple::Response) result = response.data diff --git a/spec/dnsimple/client_spec.rb b/spec/dnsimple/client_spec.rb index d454539e..83d44ba3 100644 --- a/spec/dnsimple/client_spec.rb +++ b/spec/dnsimple/client_spec.rb @@ -65,28 +65,35 @@ describe "#get" do it "delegates to #request" do - expect(subject).to receive(:execute).with(:get, "path", { foo: "bar" }).and_return(:returned) + expect(subject).to receive(:execute).with(:get, "path", nil, { foo: "bar" }).and_return(:returned) expect(subject.get("path", foo: "bar")).to eq(:returned) end end describe "#post" do it "delegates to #request" do - expect(subject).to receive(:execute).with(:post, "path", { foo: "bar" }).and_return(:returned) + expect(subject).to receive(:execute).with(:post, "path", { foo: "bar" }, {}).and_return(:returned) expect(subject.post("path", foo: "bar")).to eq(:returned) end end describe "#put" do it "delegates to #request" do - expect(subject).to receive(:execute).with(:put, "path", { foo: "bar" }).and_return(:returned) + expect(subject).to receive(:execute).with(:put, "path", { foo: "bar" }, {}).and_return(:returned) expect(subject.put("path", foo: "bar")).to eq(:returned) end end + describe "#patch" do + it "delegates to #request" do + expect(subject).to receive(:execute).with(:patch, "path", { foo: "bar" }, {}).and_return(:returned) + expect(subject.patch("path", foo: "bar")).to eq(:returned) + end + end + describe "#delete" do it "delegates to #request" do - expect(subject).to receive(:execute).with(:delete, "path", { foo: "bar" }).and_return(:returned) + expect(subject).to receive(:execute).with(:delete, "path", { foo: "bar" }, {}).and_return(:returned) expect(subject.delete("path", foo: "bar")).to eq(:returned) end end @@ -127,7 +134,7 @@ ). and_return(double('response', code: 200)) - subject.request(:get, 'foo', {}) + subject.request(:get, 'foo') end it "properly extracts options from data" do @@ -141,7 +148,7 @@ ). and_return(double('response', code: 200)) - subject.request(:put, 'foo', { something: "else", query: { foo: "bar" }, headers: { "Custom" => "Header" } }) + subject.request(:put, 'foo', { something: "else" }, { query: { foo: "bar" }, headers: { "Custom" => "Header" } }) end end diff --git a/spec/dnsimple/extra_spec.rb b/spec/dnsimple/extra_spec.rb index 8bc3545f..1c9b4e70 100644 --- a/spec/dnsimple/extra_spec.rb +++ b/spec/dnsimple/extra_spec.rb @@ -21,4 +21,26 @@ end end + describe ".validate_mandatory_attributes" do + let(:mandatory_attributes) { %i{name email} } + + it "raises an error if a mandatory attribute is not present " do + expect { + described_class.validate_mandatory_attributes({name: "foo"}, mandatory_attributes) + }.to raise_error(ArgumentError, ":email is required") + end + + it "does not raise an error if all attributes are present" do + expect { + described_class.validate_mandatory_attributes({name: "foo", email: "bar"}, mandatory_attributes) + }.not_to raise_error + end + + it "handles nil as attributes value" do + expect { + described_class.validate_mandatory_attributes(nil, mandatory_attributes) + }.to raise_error(ArgumentError, ":name is required") + end + end + end