dnsimple 2.0.0.a → 2.0.0.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +1 -2
- data/CHANGELOG.markdown +26 -2
- data/Gemfile +2 -0
- data/README.markdown +56 -36
- data/Rakefile +0 -1
- data/{dnsimple-ruby.gemspec → dnsimple.gemspec} +6 -4
- data/lib/dnsimple.rb +1 -1
- data/lib/dnsimple/base.rb +1 -1
- data/lib/dnsimple/certificate.rb +49 -35
- data/lib/dnsimple/client.rb +25 -72
- data/lib/dnsimple/contact.rb +12 -9
- data/lib/dnsimple/domain.rb +117 -82
- data/lib/dnsimple/error.rb +13 -2
- data/lib/dnsimple/extended_attribute.rb +3 -3
- data/lib/dnsimple/record.rb +9 -9
- data/lib/dnsimple/service.rb +3 -3
- data/lib/dnsimple/template.rb +8 -6
- data/lib/dnsimple/template_record.rb +8 -8
- data/lib/dnsimple/transfer_order.rb +2 -2
- data/lib/dnsimple/user.rb +26 -2
- data/lib/dnsimple/version.rb +2 -2
- data/spec/dnsimple/certificate_spec.rb +8 -5
- data/spec/dnsimple/client_spec.rb +56 -9
- data/spec/dnsimple/contact_spec.rb +2 -2
- data/spec/dnsimple/domain_spec.rb +140 -32
- data/spec/dnsimple/extended_attributes_spec.rb +1 -1
- data/spec/dnsimple/record_spec.rb +2 -2
- data/spec/dnsimple/template_spec.rb +1 -1
- data/spec/dnsimple/user_spec.rb +40 -1
- data/spec/files/2fa/error-badtoken.http +22 -0
- data/spec/files/2fa/error-required.http +23 -0
- data/spec/files/2fa/exchange-token.http +25 -0
- data/spec/files/account/user/success.http +3 -3
- data/spec/files/certificates/index/success.http +2 -2
- data/spec/files/certificates/show/notfound.http +2 -2
- data/spec/files/certificates/show/success.http +2 -2
- data/spec/files/contacts/show/notfound.http +2 -2
- data/spec/files/contacts/show/success.http +3 -3
- data/spec/files/domains/auto_renewal_disable/notfound.http +1 -1
- data/spec/files/domains/auto_renewal_disable/success.http +1 -1
- data/spec/files/domains/auto_renewal_enable/notfound.http +1 -1
- data/spec/files/domains/auto_renewal_enable/success.http +1 -1
- data/spec/files/domains/create/success.http +19 -0
- data/spec/files/domains/delete/success-204.http +18 -0
- data/spec/files/domains/delete/success.http +19 -0
- data/spec/files/domains/index/success.http +19 -0
- data/spec/files/domains/{show/notfound.http → notfound.http} +2 -2
- data/spec/files/domains/show/success.http +2 -2
- data/spec/files/extended_attributes/ca.http +2 -2
- data/spec/files/extended_attributes/com.http +2 -2
- data/spec/files/extended_attributes/success.http +2 -2
- data/spec/files/records/index/success.http +2 -2
- data/spec/files/records/show/notfound.http +2 -2
- data/spec/files/records/show/success.http +2 -2
- data/spec/files/templates/show/notfound.http +2 -2
- data/spec/files/templates/show/success.http +2 -2
- data/spec/spec_helper.rb +9 -9
- metadata +45 -33
- data/lib/dnsimple-ruby.rb +0 -1
- data/spec/ci/.dnsimple.test +0 -3
data/lib/dnsimple/contact.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Dnsimple
|
2
2
|
|
3
3
|
# Represents a contact.
|
4
4
|
class Contact < Base
|
@@ -68,7 +68,7 @@ module DNSimple
|
|
68
68
|
# pass "first" it will be resolved to "first_name", "email" is resolved
|
69
69
|
# to "email_address" and so on.
|
70
70
|
def self.resolve(name)
|
71
|
-
|
71
|
+
Contact::Aliases[name.to_s] || name
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.resolve_attributes(attributes)
|
@@ -86,7 +86,7 @@ module DNSimple
|
|
86
86
|
contact_hash = resolve_attributes(attributes)
|
87
87
|
|
88
88
|
options.merge!({:body => {:contact => contact_hash}})
|
89
|
-
response =
|
89
|
+
response = Client.post("/v1/contacts", options)
|
90
90
|
|
91
91
|
case response.code
|
92
92
|
when 201
|
@@ -97,7 +97,7 @@ module DNSimple
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def self.find(id, options={})
|
100
|
-
response =
|
100
|
+
response = Client.get("/v1/contacts/#{id}", options)
|
101
101
|
|
102
102
|
case response.code
|
103
103
|
when 200
|
@@ -110,7 +110,7 @@ module DNSimple
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def self.all(options={})
|
113
|
-
response =
|
113
|
+
response = Client.get("/v1/contacts", options)
|
114
114
|
|
115
115
|
case response.code
|
116
116
|
when 200
|
@@ -129,12 +129,12 @@ module DNSimple
|
|
129
129
|
contact_hash = {}
|
130
130
|
%w(first_name last_name organization_name job_title address1 address2 city
|
131
131
|
state_province postal_code country email_address phone phone_ext fax).each do |attribute|
|
132
|
-
contact_hash[
|
132
|
+
contact_hash[Contact.resolve(attribute)] = self.send(attribute)
|
133
133
|
end
|
134
134
|
|
135
135
|
options.merge!({:body => {:contact => contact_hash}})
|
136
136
|
|
137
|
-
response =
|
137
|
+
response = Client.put("/v1/contacts/#{id}", options)
|
138
138
|
|
139
139
|
case response.code
|
140
140
|
when 200
|
@@ -144,9 +144,12 @@ module DNSimple
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
-
#
|
147
|
+
# #delete the contact from DNSimple.
|
148
|
+
#
|
149
|
+
# WARNING: this cannot be undone.
|
150
|
+
#
|
148
151
|
def delete(options={})
|
149
|
-
|
152
|
+
Client.delete("/v1/contacts/#{id}", options)
|
150
153
|
end
|
151
154
|
alias :destroy :delete
|
152
155
|
|
data/lib/dnsimple/domain.rb
CHANGED
@@ -1,64 +1,66 @@
|
|
1
|
-
module
|
1
|
+
module Dnsimple
|
2
2
|
class Domain < Base
|
3
3
|
|
4
|
-
# The domain ID in DNSimple
|
4
|
+
# The Fixnum domain ID in DNSimple.
|
5
5
|
attr_accessor :id
|
6
6
|
|
7
|
-
# The
|
8
|
-
attr_accessor :
|
9
|
-
|
10
|
-
# When the domain was created in DNSimple
|
11
|
-
attr_accessor :created_at
|
12
|
-
|
13
|
-
# When the domain was last update in DNSimple
|
14
|
-
attr_accessor :updated_at
|
7
|
+
# The Fixnum associated user ID.
|
8
|
+
attr_accessor :user_id
|
15
9
|
|
16
|
-
# The
|
17
|
-
attr_accessor :
|
10
|
+
# The Fixnum associated registrant ID.
|
11
|
+
attr_accessor :registrant_id
|
18
12
|
|
19
|
-
#
|
20
|
-
attr_accessor :
|
13
|
+
# The String name.
|
14
|
+
attr_accessor :name
|
21
15
|
|
22
|
-
# The state
|
16
|
+
# The String state.
|
23
17
|
attr_accessor :state
|
24
18
|
|
25
|
-
#
|
26
|
-
attr_accessor :
|
19
|
+
# The String API token
|
20
|
+
attr_accessor :token
|
27
21
|
|
28
|
-
#
|
29
|
-
attr_accessor :user_id
|
30
|
-
|
31
|
-
# Is the domain lockable
|
32
|
-
attr_accessor :lockable
|
33
|
-
|
34
|
-
# Is the domain set to autorenew
|
22
|
+
# Is the domain set to auto renew?
|
35
23
|
attr_accessor :auto_renew
|
36
|
-
|
37
|
-
# Is the whois information protected
|
24
|
+
|
25
|
+
# Is the whois information protected?
|
38
26
|
attr_accessor :whois_protected
|
39
27
|
|
28
|
+
# The Date the domain will expire.
|
29
|
+
attr_accessor :expires_on
|
40
30
|
|
41
|
-
#
|
42
|
-
|
43
|
-
|
31
|
+
# The Date the domain was created in DNSimple.
|
32
|
+
attr_accessor :created_at
|
33
|
+
|
34
|
+
# The Date the domain was last update in DNSimple.
|
35
|
+
attr_accessor :updated_at
|
36
|
+
|
37
|
+
|
38
|
+
# Lists the domains in the DNSimple account.
|
39
|
+
#
|
40
|
+
# @return [Array<Domain>]
|
41
|
+
def self.list(options = {})
|
42
|
+
response = Client.get("/v1/domains", options)
|
44
43
|
|
45
44
|
case response.code
|
46
45
|
when 200
|
47
|
-
"
|
48
|
-
when 404
|
49
|
-
"available"
|
46
|
+
response.map { |r| new(r["domain"]) }
|
50
47
|
else
|
51
|
-
raise RequestError.new("Error
|
48
|
+
raise RequestError.new("Error listing domains", response)
|
52
49
|
end
|
53
50
|
end
|
54
51
|
|
55
|
-
|
56
|
-
# method returns a Domain instance if the name is created
|
57
|
-
# and raises an error otherwise.
|
58
|
-
def self.create(name, options={})
|
59
|
-
options.merge!({:body => {:domain => {:name => name}}})
|
52
|
+
def self.all(*args); list(*args); end
|
60
53
|
|
61
|
-
|
54
|
+
# Creates the domain in the DNSimple account.
|
55
|
+
#
|
56
|
+
# @param [String] name The domain name.
|
57
|
+
#
|
58
|
+
# @return [Domain] The newly created domain.
|
59
|
+
# @raise [RequestError] When the request fails.
|
60
|
+
def self.create(name)
|
61
|
+
options = { body: { domain: { name: name }}}
|
62
|
+
|
63
|
+
response = Client.post("/v1/domains", options)
|
62
64
|
|
63
65
|
case response.code
|
64
66
|
when 201
|
@@ -68,6 +70,62 @@ module DNSimple
|
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
73
|
+
# Gets a specific domain in the account.
|
74
|
+
#
|
75
|
+
# @param [Fixnum,String] id Either the numeric ID or the fully-qualified domain name.
|
76
|
+
#
|
77
|
+
# @return [Domain] The domain.
|
78
|
+
# @raise [RecordNotFound] When the domain doesn't exist.
|
79
|
+
# @raise [RequestError] When the request fails.
|
80
|
+
def self.find(id)
|
81
|
+
response = Client.get("/v1/domains/#{id}")
|
82
|
+
|
83
|
+
case response.code
|
84
|
+
when 200
|
85
|
+
new(response["domain"])
|
86
|
+
when 404
|
87
|
+
raise RecordNotFound, "Could not find domain #{id}"
|
88
|
+
else
|
89
|
+
raise RequestError.new("Error finding domain", response)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Deletes a specific domain from the account.
|
94
|
+
#
|
95
|
+
# WARNING: this cannot be undone.
|
96
|
+
#
|
97
|
+
# @param [Fixnum,String] id Either the numeric ID or the fully-qualified domain name.
|
98
|
+
#
|
99
|
+
# @return [void]
|
100
|
+
# @raise [RecordNotFound] When the domain doesn't exist.
|
101
|
+
# @raise [RequestError] When the request fails.
|
102
|
+
def self.delete(id)
|
103
|
+
response = Client.delete("/v1/domains/#{id}")
|
104
|
+
|
105
|
+
case response.code
|
106
|
+
when 200, 204
|
107
|
+
true
|
108
|
+
when 404
|
109
|
+
raise RecordNotFound, "Could not find domain #{id}"
|
110
|
+
else
|
111
|
+
raise RequestError.new("Error deleting domain", response)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Check the availability of a name
|
116
|
+
def self.check(name, options={})
|
117
|
+
response = Client.get("/v1/domains/#{name}/check", options)
|
118
|
+
|
119
|
+
case response.code
|
120
|
+
when 200
|
121
|
+
"registered"
|
122
|
+
when 404
|
123
|
+
"available"
|
124
|
+
else
|
125
|
+
raise RequestError.new("Error checking availability", response)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
71
129
|
# Purchase a domain name.
|
72
130
|
def self.register(name, registrant={}, extended_attributes={}, options={})
|
73
131
|
body = {:domain => {:name => name}}
|
@@ -75,48 +133,22 @@ module DNSimple
|
|
75
133
|
if registrant[:id]
|
76
134
|
body[:domain][:registrant_id] = registrant[:id]
|
77
135
|
else
|
78
|
-
body.merge!(:contact =>
|
136
|
+
body.merge!(:contact => Contact.resolve_attributes(registrant))
|
79
137
|
end
|
80
138
|
end
|
81
139
|
body.merge!(:extended_attribute => extended_attributes)
|
82
140
|
options.merge!({:body => body})
|
83
141
|
|
84
|
-
response =
|
142
|
+
response = Client.post("/v1/domain_registrations", options)
|
85
143
|
|
86
144
|
case response.code
|
87
145
|
when 201
|
88
|
-
return
|
146
|
+
return Domain.new(response["domain"])
|
89
147
|
else
|
90
148
|
raise RequestError.new("Error registering domain", response)
|
91
149
|
end
|
92
150
|
end
|
93
151
|
|
94
|
-
# Find a specific domain in the account either by the numeric ID
|
95
|
-
# or by the fully-qualified domain name.
|
96
|
-
def self.find(id, options={})
|
97
|
-
response = DNSimple::Client.get("/v1/domains/#{id}", options)
|
98
|
-
|
99
|
-
case response.code
|
100
|
-
when 200
|
101
|
-
new(response["domain"])
|
102
|
-
when 404
|
103
|
-
raise RecordNotFound, "Could not find domain #{id}"
|
104
|
-
else
|
105
|
-
raise RequestError.new("Error finding domain", response)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# Get all domains for the account.
|
110
|
-
def self.all(options={})
|
111
|
-
response = DNSimple::Client.get("/v1/domains", options)
|
112
|
-
|
113
|
-
case response.code
|
114
|
-
when 200
|
115
|
-
response.map { |r| new(r["domain"]) }
|
116
|
-
else
|
117
|
-
raise RequestError.new("Error listing domains", response)
|
118
|
-
end
|
119
|
-
end
|
120
152
|
|
121
153
|
# Enable auto_renew on the domain
|
122
154
|
def enable_auto_renew
|
@@ -130,10 +162,13 @@ module DNSimple
|
|
130
162
|
auto_renew!(:delete)
|
131
163
|
end
|
132
164
|
|
133
|
-
#
|
134
|
-
#
|
135
|
-
|
136
|
-
|
165
|
+
# Deletes this domain from the account.
|
166
|
+
#
|
167
|
+
# WARNING: this cannot be undone.
|
168
|
+
#
|
169
|
+
# @see .delete
|
170
|
+
def delete
|
171
|
+
self.class.delete(name)
|
137
172
|
end
|
138
173
|
alias :destroy :delete
|
139
174
|
|
@@ -143,35 +178,35 @@ module DNSimple
|
|
143
178
|
options.merge!(:body => {})
|
144
179
|
template = resolve_template(template)
|
145
180
|
|
146
|
-
|
181
|
+
Client.post("/v1/domains/#{name}/templates/#{template.id}/apply", options)
|
147
182
|
end
|
148
183
|
|
149
184
|
def resolve_template(template)
|
150
185
|
case template
|
151
|
-
when
|
186
|
+
when Template
|
152
187
|
template
|
153
188
|
else
|
154
|
-
|
189
|
+
Template.find(template)
|
155
190
|
end
|
156
191
|
end
|
157
192
|
|
158
193
|
def applied_services(options={})
|
159
|
-
response =
|
194
|
+
response = Client.get("/v1/domains/#{name}/applied_services", options)
|
160
195
|
|
161
196
|
case response.code
|
162
197
|
when 200
|
163
|
-
response.map { |r|
|
198
|
+
response.map { |r| Service.new(r["service"]) }
|
164
199
|
else
|
165
200
|
raise RequestError.new("Error listing applied services", response)
|
166
201
|
end
|
167
202
|
end
|
168
203
|
|
169
204
|
def available_services(options={})
|
170
|
-
response =
|
205
|
+
response = Client.get("/v1/domains/#{name}/available_services", options)
|
171
206
|
|
172
207
|
case response.code
|
173
208
|
when 200
|
174
|
-
response.map { |r|
|
209
|
+
response.map { |r| Service.new(r["service"]) }
|
175
210
|
else
|
176
211
|
raise RequestError.new("Error listing available services", response)
|
177
212
|
end
|
@@ -179,7 +214,7 @@ module DNSimple
|
|
179
214
|
|
180
215
|
def add_service(id_or_short_name, options={})
|
181
216
|
options.merge!(:body => {:service => {:id => id_or_short_name}})
|
182
|
-
response =
|
217
|
+
response = Client.post("/v1/domains/#{name}/applied_services", options)
|
183
218
|
|
184
219
|
case response.code
|
185
220
|
when 200
|
@@ -190,7 +225,7 @@ module DNSimple
|
|
190
225
|
end
|
191
226
|
|
192
227
|
def remove_service(id, options={})
|
193
|
-
response =
|
228
|
+
response = Client.delete("/v1/domains/#{name}/applied_services/#{id}", options)
|
194
229
|
|
195
230
|
case response.code
|
196
231
|
when 200
|
@@ -204,7 +239,7 @@ module DNSimple
|
|
204
239
|
private
|
205
240
|
|
206
241
|
def auto_renew!(method)
|
207
|
-
response =
|
242
|
+
response = Client.send(method, "/v1/domains/#{name}/auto_renewal")
|
208
243
|
case response.code
|
209
244
|
when 200
|
210
245
|
self.auto_renew = response['domain']['auto_renew']
|
data/lib/dnsimple/error.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Dnsimple
|
2
2
|
|
3
3
|
class Error < StandardError
|
4
4
|
end
|
@@ -9,13 +9,24 @@ module DNSimple
|
|
9
9
|
class RecordNotFound < Error
|
10
10
|
end
|
11
11
|
|
12
|
+
# An exception that is raised if a method is called with missing or invalid parameter values.
|
13
|
+
class ValidationError < Error
|
14
|
+
end
|
15
|
+
|
12
16
|
class RequestError < Error
|
13
17
|
def initialize(description, response)
|
14
18
|
super("#{description}: #{response["error"]}")
|
15
19
|
end
|
16
20
|
end
|
17
21
|
|
18
|
-
class
|
22
|
+
class AuthenticationError < Error
|
23
|
+
end
|
24
|
+
|
25
|
+
class AuthenticationFailed < AuthenticationError
|
26
|
+
end
|
27
|
+
|
28
|
+
# An exception that is raised if a request is executed for an account that requires two-factor authentication.
|
29
|
+
class TwoFactorAuthenticationRequired < AuthenticationError
|
19
30
|
end
|
20
31
|
|
21
32
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Dnsimple
|
2
2
|
|
3
3
|
# Used for domains that require extended attributes.
|
4
4
|
class ExtendedAttribute < Base
|
@@ -32,13 +32,13 @@ module DNSimple
|
|
32
32
|
def options=(opts)
|
33
33
|
@options = []
|
34
34
|
opts.each do |opt|
|
35
|
-
@options <<
|
35
|
+
@options << ExtendedAttribute::Option.new(opt)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
# Find the extended attributes for the given TLD
|
40
40
|
def self.find(tld, options={})
|
41
|
-
response =
|
41
|
+
response = Client.get("/v1/extended_attributes/#{tld}", options)
|
42
42
|
|
43
43
|
case response.code
|
44
44
|
when 200
|
data/lib/dnsimple/record.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module Dnsimple
|
2
2
|
|
3
3
|
class Record < Base
|
4
4
|
Aliases = {
|
@@ -16,18 +16,18 @@ module DNSimple
|
|
16
16
|
|
17
17
|
|
18
18
|
def fqdn
|
19
|
-
[name, domain.name].delete_if { |v| v !~
|
19
|
+
[name, domain.name].delete_if { |v| v !~ BLANK_REGEX }.join(".")
|
20
20
|
end
|
21
21
|
|
22
22
|
def save(options={})
|
23
23
|
record_hash = {}
|
24
24
|
%w(name content ttl prio).each do |attribute|
|
25
|
-
record_hash[
|
25
|
+
record_hash[Record.resolve(attribute)] = self.send(attribute)
|
26
26
|
end
|
27
27
|
|
28
28
|
options.merge!(:body => {:record => record_hash})
|
29
29
|
|
30
|
-
response =
|
30
|
+
response = Client.put("/v1/domains/#{domain.id}/records/#{id}", options)
|
31
31
|
|
32
32
|
case response.code
|
33
33
|
when 200
|
@@ -38,12 +38,12 @@ module DNSimple
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def delete(options={})
|
41
|
-
|
41
|
+
Client.delete("/v1/domains/#{domain.id}/records/#{id}", options)
|
42
42
|
end
|
43
43
|
alias :destroy :delete
|
44
44
|
|
45
45
|
def self.resolve(name)
|
46
|
-
|
46
|
+
Record::Aliases[name] || name
|
47
47
|
end
|
48
48
|
|
49
49
|
def self.create(domain, name, record_type, content, options={})
|
@@ -54,7 +54,7 @@ module DNSimple
|
|
54
54
|
|
55
55
|
options.merge!({:body => {:record => record_hash}})
|
56
56
|
|
57
|
-
response =
|
57
|
+
response = Client.post("/v1/domains/#{domain.name}/records", options)
|
58
58
|
|
59
59
|
case response.code
|
60
60
|
when 201
|
@@ -67,7 +67,7 @@ module DNSimple
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def self.find(domain, id, options={})
|
70
|
-
response =
|
70
|
+
response = Client.get("/v1/domains/#{domain.name}/records/#{id}", options)
|
71
71
|
|
72
72
|
case response.code
|
73
73
|
when 200
|
@@ -80,7 +80,7 @@ module DNSimple
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def self.all(domain, options={})
|
83
|
-
response =
|
83
|
+
response = Client.get("/v1/domains/#{domain.name}/records", options)
|
84
84
|
|
85
85
|
case response.code
|
86
86
|
when 200
|