transip 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -2
- data/Gemfile.lock +26 -14
- data/README.rdoc +18 -25
- data/VERSION.yml +2 -2
- data/lib/transip.rb +239 -133
- metadata +68 -49
- data/init.rb +0 -1
data/Gemfile
CHANGED
@@ -2,5 +2,6 @@ source "http://rubygems.org"
|
|
2
2
|
source 'http://gemcutter.org'
|
3
3
|
source 'http://gems.github.com'
|
4
4
|
|
5
|
-
gem 'savon', '>=
|
6
|
-
gem 'curb', '>= 0.
|
5
|
+
gem 'savon', '>= 2.3.0'
|
6
|
+
gem 'curb', '>= 0.8.4'
|
7
|
+
gem 'facets', '>= 2.9.3'
|
data/Gemfile.lock
CHANGED
@@ -3,25 +3,37 @@ GEM
|
|
3
3
|
remote: http://gemcutter.org/
|
4
4
|
remote: http://gems.github.com/
|
5
5
|
specs:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
akami (1.2.0)
|
7
|
+
gyoku (>= 0.4.0)
|
8
|
+
nokogiri (>= 1.4.0)
|
9
|
+
builder (3.2.2)
|
10
|
+
curb (0.8.4)
|
11
|
+
facets (2.9.3)
|
12
|
+
gyoku (1.1.0)
|
10
13
|
builder (>= 2.1.2)
|
11
|
-
httpi (
|
12
|
-
ntlm-http (>= 0.1.1)
|
14
|
+
httpi (2.1.0)
|
13
15
|
rack
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
rubyntlm (~> 0.3.2)
|
17
|
+
nokogiri (1.5.10)
|
18
|
+
nori (2.3.0)
|
19
|
+
rack (1.5.2)
|
20
|
+
rubyntlm (0.3.4)
|
21
|
+
savon (2.3.0)
|
22
|
+
akami (~> 1.2.0)
|
17
23
|
builder (>= 2.1.2)
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
gyoku (~> 1.1.0)
|
25
|
+
httpi (~> 2.1.0)
|
26
|
+
nokogiri (>= 1.4.0, < 1.6)
|
27
|
+
nori (~> 2.3.0)
|
28
|
+
wasabi (~> 3.2.0)
|
29
|
+
wasabi (3.2.0)
|
30
|
+
httpi (~> 2.0)
|
31
|
+
nokogiri (>= 1.4.0, < 1.6)
|
21
32
|
|
22
33
|
PLATFORMS
|
23
34
|
ruby
|
24
35
|
|
25
36
|
DEPENDENCIES
|
26
|
-
curb
|
27
|
-
|
37
|
+
curb (>= 0.8.4)
|
38
|
+
facets (>= 2.9.3)
|
39
|
+
savon (>= 2.3.0)
|
data/README.rdoc
CHANGED
@@ -1,48 +1,41 @@
|
|
1
1
|
= TransIP API
|
2
2
|
|
3
|
-
Ruby gem to use the full TransIP API (
|
3
|
+
Ruby gem to use the full TransIP API (v4.2). This fork uses an updated version of savon, and implements the new request signing method that the guys at TransIP have introduced into their api. So far, i have only tested the :get_domain_names, :get_info and :set_dns_entries calls.
|
4
|
+
|
5
|
+
|
6
|
+
The transip API makes use of public/private key encryption. You need to use the TransIP
|
7
|
+
control panel to give your server access to the api, and to generate a key. You can then
|
8
|
+
use the key together with your username to gain access to the api
|
4
9
|
|
5
10
|
For more info see:
|
6
11
|
|
7
|
-
* <b>The origin of this code:</b> https://github.com/joost/transip
|
12
|
+
* <b>The origin of this code:</b> https://github.com/joost/transip
|
8
13
|
* <b>TransIP API Docs:</b> https://www.transip.nl/g/api
|
9
14
|
|
10
|
-
Credits
|
11
|
-
|
12
|
-
* <b>Savon Gem:</b> See: http://savonrb.com. Wouldn't be so simple without it!
|
15
|
+
Credits for full rewrite to work with new TransIP API version go to Richard Bronkhorst (https://github.com/richmans).
|
13
16
|
|
14
17
|
== Install
|
15
18
|
|
16
|
-
Use the gem.
|
17
|
-
|
18
|
-
gem install transip
|
19
|
-
|
20
19
|
For the latest version: Download / clone the repository. Bundle install the needed gems and require the lib.
|
21
20
|
|
22
|
-
git clone git://github.com/joost/transip
|
21
|
+
git clone git://github.com/joost/transip.git
|
22
|
+
cd transip
|
23
23
|
bundle install
|
24
|
-
irb # and require './transip'
|
24
|
+
irb # and require './lib/transip'
|
25
25
|
|
26
26
|
== Usage
|
27
27
|
|
28
28
|
For the most up-to-date documentation see the source files. Use as follows:
|
29
29
|
|
30
|
-
|
31
|
-
transip
|
32
|
-
transip = Transip.new(:username => 'api_username', :ip => '12.34.12.3', :mode => 'readwrite') # use this in production
|
33
|
-
transip.actions # => [:check_availability, :get_whois, :get_domain_names, :get_info, :get_auth_code, :get_is_locked, :register, :cancel, :transfer_with_owner_change, :transfer_without_owner_change, :set_nameservers, :set_lock, :unset_lock, :set_dns_entries, :set_owner, :set_contacts]
|
30
|
+
transip = Transip.new(:username => 'api_username', :key => private_key, :ip => '12.34.12.3', :mode => 'readwrite') # use this in production
|
31
|
+
transip.actions # => [:check_availability, :get_whois, :get_domain_names, :get_info, :get_auth_code, :get_is_locked, register, :cancel, :transfer_with_owner_change, :transfer_without_owner_change, :set_nameservers, :set_lock, unset_lock, :set_dns_entries, :set_owner, :set_contacts]
|
34
32
|
transip.request(:get_domain_names)
|
35
|
-
transip.request(:get_info, :domain_name => '
|
36
|
-
transip.
|
37
|
-
transip.
|
38
|
-
transip.request(:
|
39
|
-
transip.request(:set_dns_entries, :domain_name => 'bdgg.nl', :dns_entries => [Transip::DnsEntry.new('test', 5.minutes, 'A', '74.125.77.147')])
|
40
|
-
transip.request(:register, Transip::Domain.new('newdomain.com', nil, nil, [Transip::DnsEntry.new('test', 5.minutes, 'A', '74.125.77.147')]))
|
41
|
-
|
42
|
-
== TODO
|
33
|
+
transip.request(:get_info, :domain_name => 'example.com')
|
34
|
+
transip.request(:get_whois, :domain_name => 'example.com')
|
35
|
+
transip.request(:set_dns_entries, :domain_name => 'example.com', :dns_entries => [Transip::DnsEntry.new('test', 5.inutes, 'A', '74.125.77.147')])
|
36
|
+
transip.request(:register, Transip::Domain.new('example.com', nil, nil, [Transip::DnsEntry.new('test', 5.minutes, 'A', '74.125.77.147')]))
|
43
37
|
|
44
|
-
* Tests
|
45
38
|
|
46
39
|
Please feel free to contribute and send me a pull request via Github!
|
47
40
|
|
48
|
-
Copyright (c)
|
41
|
+
Copyright (c) 2013 Richard Bronkhorst, released under the MIT license
|
data/VERSION.yml
CHANGED
data/lib/transip.rb
CHANGED
@@ -1,56 +1,37 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
require "bundler/setup"
|
3
|
-
|
3
|
+
require 'securerandom'
|
4
4
|
require 'savon'
|
5
5
|
require 'curb'
|
6
|
-
require '
|
6
|
+
require 'facets'
|
7
|
+
require 'digest/sha2'
|
8
|
+
require 'base64'
|
9
|
+
require 'ipaddr'
|
7
10
|
#
|
8
|
-
# Implements the www.transip.nl API (
|
11
|
+
# Implements the www.transip.nl API (v4.2). For more info see: https://www.transip.nl/g/api/
|
9
12
|
#
|
13
|
+
# The transip API makes use of public/private key encryption. You need to use the TransIP
|
14
|
+
# control panel to give your server access to the api, and to generate a key. You can then
|
15
|
+
# use the key together with your username to gain access to the api
|
10
16
|
# Usage:
|
11
|
-
# transip = Transip.new(:username => 'api_username'
|
12
|
-
# transip = Transip.new(:username => 'api_username', :ip => '12.34.12.3', :mode => 'readwrite') # use this in production
|
17
|
+
# transip = Transip.new(:username => 'api_username', :key => private_key, :ip => '12.34.12.3', :mode => 'readwrite') # use this in production
|
13
18
|
# transip.actions # => [:check_availability, :get_whois, :get_domain_names, :get_info, :get_auth_code, :get_is_locked, :register, :cancel, :transfer_with_owner_change, :transfer_without_owner_change, :set_nameservers, :set_lock, :unset_lock, :set_dns_entries, :set_owner, :set_contacts]
|
14
19
|
# transip.request(:get_domain_names)
|
15
|
-
# transip.request(:get_info, :domain_name => '
|
16
|
-
# transip.
|
17
|
-
# transip.
|
18
|
-
# transip.request(:
|
19
|
-
# transip.request(:set_dns_entries, :domain_name => 'bdgg.nl', :dns_entries => [Transip::DnsEntry.new('test', 5.minutes, 'A', '74.125.77.147')])
|
20
|
-
# transip.request(:register, Transip::Domain.new('newdomain.com', nil, nil, [Transip::DnsEntry.new('test', 5.minutes, 'A', '74.125.77.147')]))
|
21
|
-
#
|
22
|
-
# Some other methods:
|
23
|
-
# transip.generate_hash # Use this to generate a authentication hash
|
24
|
-
# transip.hash = 'your_hash' # Or use this to directly set the hash (so you don't have to use your password in your code)
|
25
|
-
# transip.client! # This returns a new Savon::Client. It is cached in transip.client so when you update your username, password or hash call this method!
|
20
|
+
# transip.request(:get_info, :domain_name => 'example.com')
|
21
|
+
# transip.request(:get_whois, :domain_name => 'example.com')
|
22
|
+
# transip.request(:set_dns_entries, :domain_name => 'example.com', :dns_entries => [Transip::DnsEntry.new('test', 5.minutes, 'A', '74.125.77.147')])
|
23
|
+
# transip.request(:register, Transip::Domain.new('example.com', nil, nil, [Transip::DnsEntry.new('test', 5.minutes, 'A', '74.125.77.147')]))
|
26
24
|
#
|
27
|
-
# Credits:
|
28
|
-
# Savon Gem - See: http://savonrb.com/. Wouldn't be so simple without it!
|
29
25
|
class Transip
|
30
|
-
|
26
|
+
SERVICE = 'DomainService'
|
31
27
|
WSDL = 'https://api.transip.nl/wsdl/?service=DomainService'
|
28
|
+
API_VERSION = '4.2'
|
32
29
|
|
33
30
|
attr_accessor :username, :password, :ip, :mode, :hash
|
34
31
|
attr_reader :response
|
35
32
|
|
36
33
|
# Following Error needs to be catched in your code!
|
37
34
|
class ApiError < RuntimeError
|
38
|
-
|
39
|
-
IP4_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
|
40
|
-
|
41
|
-
# Returns true if we have a authentication error and gets ip from error msg.
|
42
|
-
# "Wrong API credentials (bad hash); called from IP 213.86.41.114"
|
43
|
-
def ip4_authentication_error?
|
44
|
-
self.message.to_s =~ /called from IP\s(#{IP4_REGEXP})/ # "Wrong API credentials (bad hash); called from IP 213.86.41.114"
|
45
|
-
@error_msg_ip = $1
|
46
|
-
!@error_msg_ip.nil?
|
47
|
-
end
|
48
|
-
|
49
|
-
# Returns the ip coming from the error msg.
|
50
|
-
def error_msg_ip
|
51
|
-
@error_msg_ip || ip4_authentication_error? && @error_msg_ip
|
52
|
-
end
|
53
|
-
|
54
35
|
end
|
55
36
|
|
56
37
|
# Following subclasses are actually not needed (as you can also
|
@@ -72,9 +53,9 @@ class Transip
|
|
72
53
|
end
|
73
54
|
|
74
55
|
# Gyoku.xml (see: https://github.com/rubiii/gyoku) is used by Savon.
|
75
|
-
# It calls to_s on unknown Objects. We use it to convert
|
56
|
+
# It calls to_s on unknown Objects. We use it to convert
|
76
57
|
def to_s
|
77
|
-
Gyoku.xml(self.
|
58
|
+
Gyoku.xml(self.members_to_hash)
|
78
59
|
end
|
79
60
|
|
80
61
|
# See what happens here: http://snippets.dzone.com/posts/show/302
|
@@ -86,6 +67,50 @@ class Transip
|
|
86
67
|
{ self.class_name_to_sym => self.members_to_hash }
|
87
68
|
end
|
88
69
|
|
70
|
+
def self.get_type(hash)
|
71
|
+
type = hash[:'@xsi:type'].split(":").last
|
72
|
+
raise "No type definition found in hash" if type.nil?
|
73
|
+
klass = Transip.const_get(type) rescue nil
|
74
|
+
raise "Invalid transipStruct #{type}" unless klass < TransipStruct
|
75
|
+
klass
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.from_hash(hash)
|
79
|
+
begin
|
80
|
+
result = get_type(hash).new
|
81
|
+
rescue
|
82
|
+
return hash
|
83
|
+
end
|
84
|
+
hash.each do |key, value|
|
85
|
+
next if key[0] == '@'
|
86
|
+
result.send(:"#{key}=", from_soap(value))
|
87
|
+
end
|
88
|
+
result
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.from_soap(input)
|
92
|
+
if input.is_a? Array
|
93
|
+
result = input.map {|value| from_soap(value)}
|
94
|
+
elsif input.is_a? Hash
|
95
|
+
|
96
|
+
if input.keys.first == :item
|
97
|
+
result = from_soap(input[:item])
|
98
|
+
elsif input[:'@xsi:type'] == 'xsd:string'
|
99
|
+
result = ''
|
100
|
+
else
|
101
|
+
result = TransipStruct.from_hash(input)
|
102
|
+
end
|
103
|
+
# this is not a transip struct
|
104
|
+
if result.is_a? Hash
|
105
|
+
result.each do |key, value|
|
106
|
+
result[key] = from_soap(value)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
else
|
110
|
+
result = input
|
111
|
+
end
|
112
|
+
result
|
113
|
+
end
|
89
114
|
end
|
90
115
|
|
91
116
|
# name - String (Eg. '@' or 'www')
|
@@ -98,7 +123,7 @@ class Transip
|
|
98
123
|
# hostname - string
|
99
124
|
# ipv4 - string
|
100
125
|
# ipv6 - string (optional)
|
101
|
-
class Nameserver < TransipStruct.new(:
|
126
|
+
class Nameserver < TransipStruct.new(:hostname, :ipv4, :ipv6)
|
102
127
|
end
|
103
128
|
|
104
129
|
# type - string
|
@@ -134,28 +159,45 @@ class Transip
|
|
134
159
|
# contacts - Array of Transip::WhoisContact
|
135
160
|
# dns_entries - Array of Transip::DnsEntry
|
136
161
|
# branding - Transip::DomainBranding
|
137
|
-
|
162
|
+
# auth_code - String
|
163
|
+
# is_locked - boolean
|
164
|
+
# registration_date - DateTime
|
165
|
+
# renewal_date - DateTime
|
166
|
+
class Domain < TransipStruct.new(:name, :nameservers, :contacts, :dns_entries, :branding, :auth_code, :is_locked, :registration_date, :renewal_date)
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
# name - String
|
171
|
+
# price - number
|
172
|
+
# renewal_price - number
|
173
|
+
# capabilities - Array of strings
|
174
|
+
# registration_period_length - number
|
175
|
+
# cancel_time_frame - number
|
176
|
+
class Tld < TransipStruct.new(:name, :price, :renewal_price, :capabilities, :registration_period_length, :cancel_time_frame)
|
138
177
|
end
|
139
178
|
|
140
179
|
# Options:
|
141
|
-
# * username
|
180
|
+
# * username
|
142
181
|
# * ip
|
143
|
-
# *
|
182
|
+
# * key
|
144
183
|
# * mode
|
145
184
|
#
|
146
185
|
# Example:
|
147
|
-
# transip = Transip.new(:username => 'api_username'
|
148
|
-
# transip = Transip.new(:username => 'api_username', :ip => '12.34.12.3', :mode => 'readwrite') # use this in production
|
186
|
+
# transip = Transip.new(:username => 'api_username', :ip => '12.34.12.3', :key => mykey, :mode => 'readwrite') # use this in production
|
149
187
|
def initialize(options = {})
|
188
|
+
@key = options[:key]
|
150
189
|
@username = options[:username]
|
151
|
-
|
152
|
-
|
190
|
+
@ip = options[:ip]
|
191
|
+
raise ArgumentError, "The :username, :ip and :key options are required!" if @username.nil? or @key.nil?
|
192
|
+
|
153
193
|
@mode = options[:mode] || :readonly
|
194
|
+
@endpoint = options[:endpoint] || 'api.transip.nl'
|
154
195
|
if options[:password]
|
155
196
|
@password = options[:password]
|
156
|
-
self.generate_hash
|
157
197
|
end
|
158
|
-
|
198
|
+
@savon_options = {
|
199
|
+
:wsdl => WSDL
|
200
|
+
}
|
159
201
|
# By default we don't want to debug!
|
160
202
|
self.turn_off_debugging!
|
161
203
|
end
|
@@ -163,59 +205,127 @@ class Transip
|
|
163
205
|
# By default we don't want to debug!
|
164
206
|
# Changing might impact other Savon usages.
|
165
207
|
def turn_off_debugging!
|
166
|
-
|
167
|
-
|
168
|
-
|
208
|
+
@savon_options[:log] = false # disable logging
|
209
|
+
@savon_options[:log_level] = :info # changing the log level
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
# Make Savon log to Rails.logger and turn_off_debugging!
|
214
|
+
def use_with_rails!
|
215
|
+
if Rails.env.production?
|
216
|
+
self.turn_off_debugging!
|
169
217
|
end
|
218
|
+
@savon_options[:logger] = Rails.logger # using the Rails logger
|
170
219
|
end
|
171
220
|
|
172
|
-
#
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
config.log_level = :debug
|
221
|
+
# yes, i know, it smells bad
|
222
|
+
def convert_array_to_hash(array)
|
223
|
+
result = {}
|
224
|
+
array.each_with_index do |value, index|
|
225
|
+
result[index] = value
|
178
226
|
end
|
227
|
+
result
|
179
228
|
end
|
180
229
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
230
|
+
def urlencode(input)
|
231
|
+
output = URI.encode_www_form_component(input)
|
232
|
+
output.gsub!('+', '%20')
|
233
|
+
output.gsub!('%7E', '~')
|
234
|
+
output
|
235
|
+
end
|
236
|
+
|
237
|
+
def serialize_parameters(parameters, key_prefix=nil)
|
238
|
+
parameters = parameters.to_hash.values.first if parameters.is_a? TransipStruct
|
239
|
+
parameters = convert_array_to_hash(parameters) if parameters.is_a? Array
|
240
|
+
if not parameters.is_a? Hash
|
241
|
+
return urlencode(parameters)
|
242
|
+
end
|
243
|
+
|
244
|
+
encoded_parameters = []
|
245
|
+
parameters.each do |key, value|
|
246
|
+
next if key.to_s == '@xsi:type'
|
247
|
+
encoded_key = (key_prefix.nil?) ? urlencode(key) : "#{key_prefix}[#{urlencode(key)}]"
|
248
|
+
if value.is_a? Hash or value.is_a? Array or value.is_a? TransipStruct
|
249
|
+
encoded_parameters << serialize_parameters(value, encoded_key)
|
250
|
+
else
|
251
|
+
encoded_value = urlencode(value)
|
252
|
+
encoded_parameters << "#{encoded_key}=#{encoded_value}"
|
188
253
|
end
|
189
|
-
config.logger = Rails.logger # using the Rails logger
|
190
254
|
end
|
255
|
+
|
256
|
+
encoded_parameters = encoded_parameters.join("&")
|
257
|
+
#puts encoded_parameters.split('&').join("\n")
|
258
|
+
encoded_parameters
|
191
259
|
end
|
192
260
|
|
193
|
-
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
261
|
+
|
262
|
+
# does all the techy stuff to calculate transip's sick authentication scheme:
|
263
|
+
# a hash with all the request information is subsequently:
|
264
|
+
# serialized like a www form
|
265
|
+
# SHA512 digested
|
266
|
+
# asn1 header added
|
267
|
+
# private key encrypted
|
268
|
+
# Base64 encoded
|
269
|
+
# URL encoded
|
270
|
+
# I think the guys at transip were trying to use their entire crypto-toolbox!
|
271
|
+
def signature(method, parameters, time, nonce)
|
272
|
+
formatted_method = method.to_s.lower_camelcase
|
273
|
+
parameters ||= {}
|
274
|
+
input = convert_array_to_hash(parameters.values)
|
275
|
+
options = {
|
276
|
+
'__method' => formatted_method,
|
277
|
+
'__service' => SERVICE,
|
278
|
+
'__hostname' => @endpoint,
|
279
|
+
'__timestamp' => time,
|
280
|
+
'__nonce' => nonce
|
281
|
+
|
282
|
+
}
|
283
|
+
input.merge!(options)
|
284
|
+
raise "Invalid RSA key" unless @key =~ /-----BEGIN RSA PRIVATE KEY-----(.*)-----END RSA PRIVATE KEY-----/sim
|
285
|
+
serialized_input = serialize_parameters(input)
|
286
|
+
|
287
|
+
digest = Digest::SHA512.new.digest(serialized_input)
|
288
|
+
asn_header = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40"
|
289
|
+
asn = asn_header + digest
|
290
|
+
private_key = OpenSSL::PKey::RSA.new(@key)
|
291
|
+
encrypted_asn = private_key.private_encrypt(asn)
|
292
|
+
readable_encrypted_asn = Base64.encode64(encrypted_asn)
|
293
|
+
urlencode(readable_encrypted_asn)
|
203
294
|
end
|
204
295
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
296
|
+
def to_cookies(content)
|
297
|
+
content.map do |item|
|
298
|
+
HTTPI::Cookie.new item
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
# Used for authentication
|
304
|
+
def cookies(method, parameters)
|
305
|
+
time = Time.new.to_i
|
306
|
+
#strip out the -'s because transip requires the nonce to be between 6 and 32 chars
|
307
|
+
nonce = SecureRandom.uuid.gsub("-", '')
|
308
|
+
result = to_cookies [ "login=#{self.username}",
|
309
|
+
"mode=#{self.mode}",
|
310
|
+
"timestamp=#{time}",
|
311
|
+
"nonce=#{nonce}",
|
312
|
+
"clientVersion=#{API_VERSION}",
|
313
|
+
"signature=#{signature(method, parameters, time, nonce)}"
|
314
|
+
|
315
|
+
]
|
316
|
+
#puts signature(method, parameters, time, nonce)
|
317
|
+
result
|
209
318
|
end
|
210
319
|
|
211
320
|
# Same as client method but initializes a brand new fresh client.
|
212
321
|
# You have to use this one when you want to re-set the mode (readwrite, readonly),
|
213
322
|
# or authentication details of your client.
|
214
323
|
def client!
|
215
|
-
@client = Savon::Client.new do
|
216
|
-
|
324
|
+
@client = Savon::Client.new(@savon_options) do
|
325
|
+
namespaces(
|
326
|
+
"xmlns:enc" => "http://schemas.xmlsoap.org/soap/encoding/"
|
327
|
+
)
|
217
328
|
end
|
218
|
-
@client.http.headers["Cookie"] = cookie
|
219
329
|
return @client
|
220
330
|
end
|
221
331
|
|
@@ -230,65 +340,61 @@ class Transip
|
|
230
340
|
client.wsdl.soap_actions
|
231
341
|
end
|
232
342
|
|
233
|
-
#
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
343
|
+
# This makes sure that arrays are properly encoded as soap-arrays by Gyoku
|
344
|
+
def fix_array_definitions(options)
|
345
|
+
result = {}
|
346
|
+
options.each do |key, value|
|
347
|
+
if value.is_a? Array and value.size > 0
|
348
|
+
entry_name = value.first.class.name.split(":").last
|
349
|
+
result[key] = {
|
350
|
+
'item' => {:content! => value, :'@xsi:type' => "tns:#{entry_name}"},
|
351
|
+
:'@xsi:type' => "tns:ArrayOf#{entry_name}",
|
352
|
+
:'@enc:arrayType' => "tns:#{entry_name}[#{value.size}]"
|
353
|
+
}
|
354
|
+
else
|
355
|
+
result[key] = value
|
245
356
|
end
|
246
|
-
elsif options.class < Transip::TransipStruct
|
247
|
-
# If we call request(:register, Transip::Domain.new('newdomain.com')) we turn the Transip::Domain into a Hash.
|
248
|
-
@response = client.request(action) do
|
249
|
-
soap.body = options.to_hash
|
250
|
-
end
|
251
|
-
else
|
252
|
-
raise ArgumentError, "Expected options to be nil or a Hash!"
|
253
357
|
end
|
254
|
-
|
255
|
-
rescue Savon::SOAP::Fault => e
|
256
|
-
raise ApiError.new(e), e.message.sub(/^\(\d+\)\s+/,'') # We raise our own error (FIXME: Correct?).
|
257
|
-
# TODO: Curl::Err::HostResolutionError, Couldn't resolve host name
|
358
|
+
result
|
258
359
|
end
|
259
360
|
|
260
|
-
# This is voodoo. Use it only if you know voodoo kung-fu.
|
261
|
-
#
|
262
|
-
# The method fixes the ip that is set. It uses the error from
|
263
|
-
# Transip to set the ip and re-request an authentication hash.
|
264
|
-
#
|
265
|
-
# It only works if you set password (via the password= method)!
|
266
|
-
def request_with_ip4_fix(*args)
|
267
|
-
self.request(*args)
|
268
|
-
rescue ApiError => e
|
269
|
-
if e.ip4_authentication_error?
|
270
|
-
if !(@ip == e.error_msg_ip) # If not the same IP we try it with this IP..
|
271
|
-
self.ip = e.error_msg_ip
|
272
|
-
self.generate_hash # Generate a new authentication hash.
|
273
|
-
self.client! # Update the client with the new authentication hash in the cookie!
|
274
|
-
return self.request(*args)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
raise # If we haven't returned anything.. we raise the ApiError again.
|
278
|
-
end
|
279
361
|
|
280
|
-
|
362
|
+
# converts the savon response object to something we can return to the caller
|
363
|
+
# - A TransipStruct object
|
364
|
+
# - An array of TransipStructs
|
365
|
+
# - nil
|
366
|
+
def process_response(response)
|
367
|
+
response = response.to_hash.values.first[:return] rescue nil
|
368
|
+
TransipStruct.from_soap(response)
|
281
369
|
|
282
|
-
|
283
|
-
def self.local_ip
|
284
|
-
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
|
370
|
+
end
|
285
371
|
|
286
|
-
|
287
|
-
|
288
|
-
|
372
|
+
# This is the main request function
|
373
|
+
# throws ApiError
|
374
|
+
# returns response object (can be TransipStruct or Array of TransipStruct)
|
375
|
+
def request(action, options = nil)
|
376
|
+
formatted_action = action.to_s.lower_camelcase
|
377
|
+
parameters = {
|
378
|
+
# for some reason, the transip server wants the body root tag to be
|
379
|
+
# the name of the action.
|
380
|
+
:message_tag => formatted_action
|
381
|
+
}
|
382
|
+
options = options.to_hash if options.is_a? Transip::TransipStruct
|
383
|
+
|
384
|
+
if options.is_a? Hash
|
385
|
+
xml_options = fix_array_definitions(options)
|
386
|
+
elsif options.nil?
|
387
|
+
xml_options = nil
|
388
|
+
else
|
389
|
+
raise "Invalid parameter format (should be nil, hash or TransipStruct"
|
289
390
|
end
|
290
|
-
|
291
|
-
|
292
|
-
|
391
|
+
parameters[:message] = xml_options
|
392
|
+
parameters[:cookies] = cookies(action, options)
|
393
|
+
#puts parameters.inspect
|
394
|
+
response = client.call(action, parameters)
|
293
395
|
|
396
|
+
process_response(response)
|
397
|
+
rescue Savon::SOAPFault => e
|
398
|
+
raise ApiError.new(e), e.message.sub(/^\(\d+\)\s+/,'') # We raise our own error (FIXME: Correct?).
|
399
|
+
end
|
294
400
|
end
|
metadata
CHANGED
@@ -1,84 +1,103 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: transip
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.0
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Joost Hietbrink
|
9
|
+
- Richard Bronkhorst
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2013-09-10 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
17
16
|
name: savon
|
18
|
-
|
19
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
20
18
|
none: false
|
21
|
-
requirements:
|
22
|
-
- -
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version:
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.3.0
|
25
23
|
type: :runtime
|
26
|
-
|
27
|
-
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 2.3.0
|
31
|
+
- !ruby/object:Gem::Dependency
|
28
32
|
name: curb
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.8.4
|
39
|
+
type: :runtime
|
29
40
|
prerelease: false
|
30
|
-
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
42
|
none: false
|
32
|
-
requirements:
|
33
|
-
- -
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: 0.
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.8.4
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: facets
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.9.3
|
36
55
|
type: :runtime
|
37
|
-
|
38
|
-
|
39
|
-
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 2.9.3
|
63
|
+
description: Ruby gem to use the full TransIP API (v4.2).
|
64
|
+
email:
|
40
65
|
executables: []
|
41
|
-
|
42
66
|
extensions: []
|
43
|
-
|
44
|
-
extra_rdoc_files:
|
67
|
+
extra_rdoc_files:
|
45
68
|
- MIT-LICENSE
|
46
69
|
- README.rdoc
|
47
|
-
files:
|
70
|
+
files:
|
48
71
|
- MIT-LICENSE
|
49
72
|
- README.rdoc
|
50
73
|
- VERSION.yml
|
51
74
|
- Gemfile
|
52
75
|
- Gemfile.lock
|
53
|
-
- init.rb
|
54
76
|
- lib/transip.rb
|
55
|
-
|
56
|
-
homepage: http://github.com/joost/transip-api
|
77
|
+
homepage: http://github.com/richmans/transip-api
|
57
78
|
licenses: []
|
58
|
-
|
59
79
|
post_install_message:
|
60
|
-
rdoc_options:
|
80
|
+
rdoc_options:
|
61
81
|
- --charset=UTF-8
|
62
|
-
require_paths:
|
82
|
+
require_paths:
|
63
83
|
- lib
|
64
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
85
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version:
|
70
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
91
|
none: false
|
72
|
-
requirements:
|
73
|
-
- -
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version:
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
76
96
|
requirements: []
|
77
|
-
|
78
97
|
rubyforge_project:
|
79
|
-
rubygems_version: 1.
|
98
|
+
rubygems_version: 1.8.25
|
80
99
|
signing_key:
|
81
100
|
specification_version: 3
|
82
|
-
summary: Ruby gem to use the full TransIP API (
|
101
|
+
summary: Ruby gem to use the full TransIP API (v4.2).
|
83
102
|
test_files: []
|
84
|
-
|
103
|
+
has_rdoc: true
|
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'transip-api'
|