epp-client 0.0.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.simplecov +16 -0
  4. data/.travis.yml +11 -0
  5. data/.yardopts +4 -0
  6. data/Gemfile +20 -0
  7. data/Gemfile.lock +51 -0
  8. data/LICENSE +1 -1
  9. data/README.md +75 -0
  10. data/Rakefile +2 -37
  11. data/epp-client.gemspec +15 -58
  12. data/gemfiles/Gemfile.ruby18 +13 -0
  13. data/lib/epp-client.rb +94 -7
  14. data/lib/epp-client/client.rb +117 -20
  15. data/lib/epp-client/commands/check.rb +11 -0
  16. data/lib/epp-client/commands/command.rb +24 -0
  17. data/lib/epp-client/commands/create.rb +11 -0
  18. data/lib/epp-client/commands/delete.rb +11 -0
  19. data/lib/epp-client/commands/info.rb +11 -0
  20. data/lib/epp-client/commands/login.rb +40 -0
  21. data/lib/epp-client/commands/logout.rb +11 -0
  22. data/lib/epp-client/commands/poll.rb +28 -0
  23. data/lib/epp-client/commands/read_write_command.rb +18 -0
  24. data/lib/epp-client/commands/renew.rb +11 -0
  25. data/lib/epp-client/commands/transfer.rb +25 -0
  26. data/lib/epp-client/commands/update.rb +11 -0
  27. data/lib/epp-client/contact/check.rb +23 -0
  28. data/lib/epp-client/contact/check_response.rb +22 -0
  29. data/lib/epp-client/contact/command.rb +87 -0
  30. data/lib/epp-client/contact/create.rb +34 -0
  31. data/lib/epp-client/contact/create_response.rb +14 -0
  32. data/lib/epp-client/contact/delete.rb +21 -0
  33. data/lib/epp-client/contact/delete_response.rb +9 -0
  34. data/lib/epp-client/contact/info.rb +21 -0
  35. data/lib/epp-client/contact/info_response.rb +74 -0
  36. data/lib/epp-client/contact/response.rb +34 -0
  37. data/lib/epp-client/contact/transfer.rb +21 -0
  38. data/lib/epp-client/contact/transfer_response.rb +26 -0
  39. data/lib/epp-client/contact/update.rb +80 -0
  40. data/lib/epp-client/contact/update_response.rb +9 -0
  41. data/lib/epp-client/domain/check.rb +23 -0
  42. data/lib/epp-client/domain/check_response.rb +22 -0
  43. data/lib/epp-client/domain/command.rb +92 -0
  44. data/lib/epp-client/domain/create.rb +49 -0
  45. data/lib/epp-client/domain/create_response.rb +17 -0
  46. data/lib/epp-client/domain/delete.rb +21 -0
  47. data/lib/epp-client/domain/delete_response.rb +9 -0
  48. data/lib/epp-client/domain/info.rb +21 -0
  49. data/lib/epp-client/domain/info_response.rb +66 -0
  50. data/lib/epp-client/domain/renew.rb +34 -0
  51. data/lib/epp-client/domain/renew_response.rb +14 -0
  52. data/lib/epp-client/domain/response.rb +34 -0
  53. data/lib/epp-client/domain/transfer.rb +27 -0
  54. data/lib/epp-client/domain/transfer_response.rb +29 -0
  55. data/lib/epp-client/domain/update.rb +81 -0
  56. data/lib/epp-client/domain/update_response.rb +9 -0
  57. data/lib/epp-client/host/check.rb +23 -0
  58. data/lib/epp-client/host/check_response.rb +22 -0
  59. data/lib/epp-client/host/command.rb +47 -0
  60. data/lib/epp-client/host/create.rb +24 -0
  61. data/lib/epp-client/host/create_response.rb +14 -0
  62. data/lib/epp-client/host/delete.rb +21 -0
  63. data/lib/epp-client/host/delete_response.rb +9 -0
  64. data/lib/epp-client/host/info.rb +21 -0
  65. data/lib/epp-client/host/info_response.rb +42 -0
  66. data/lib/epp-client/host/response.rb +34 -0
  67. data/lib/epp-client/host/update.rb +76 -0
  68. data/lib/epp-client/host/update_response.rb +9 -0
  69. data/lib/epp-client/request.rb +29 -74
  70. data/lib/epp-client/requests/abstract.rb +30 -0
  71. data/lib/epp-client/requests/command.rb +28 -0
  72. data/lib/epp-client/requests/extension.rb +28 -0
  73. data/lib/epp-client/requests/hello.rb +12 -0
  74. data/lib/epp-client/response.rb +45 -8
  75. data/lib/epp-client/response_helper.rb +25 -0
  76. data/lib/epp-client/server.rb +167 -63
  77. data/lib/epp-client/testing.rb +59 -0
  78. data/lib/epp-client/version.rb +3 -0
  79. data/lib/epp-client/xml_helper.rb +71 -0
  80. data/test/commands/test_check_command.rb +33 -0
  81. data/test/commands/test_create_command.rb +53 -0
  82. data/test/commands/test_delete_command.rb +28 -0
  83. data/test/commands/test_info_command.rb +28 -0
  84. data/test/commands/test_login_command.rb +56 -0
  85. data/test/commands/test_logout_command.rb +22 -0
  86. data/test/commands/test_poll_command.rb +54 -0
  87. data/test/commands/test_renew_command.rb +39 -0
  88. data/test/commands/test_transfer_command.rb +37 -0
  89. data/test/commands/test_update_command.rb +60 -0
  90. data/test/contact/test_contact_check.rb +33 -0
  91. data/test/contact/test_contact_check_response.rb +38 -0
  92. data/test/contact/test_contact_create.rb +70 -0
  93. data/test/contact/test_contact_create_response.rb +33 -0
  94. data/test/contact/test_contact_delete.rb +28 -0
  95. data/test/contact/test_contact_delete_response.rb +23 -0
  96. data/test/contact/test_contact_info.rb +28 -0
  97. data/test/contact/test_contact_info_response.rb +100 -0
  98. data/test/contact/test_contact_transfer.rb +28 -0
  99. data/test/contact/test_contact_transfer_response.rb +100 -0
  100. data/test/contact/test_contact_update.rb +83 -0
  101. data/test/contact/test_contact_update_response.rb +23 -0
  102. data/test/domain/test_domain_check.rb +33 -0
  103. data/test/domain/test_domain_check_response.rb +38 -0
  104. data/test/domain/test_domain_create.rb +53 -0
  105. data/test/domain/test_domain_create_response.rb +39 -0
  106. data/test/domain/test_domain_delete.rb +28 -0
  107. data/test/domain/test_domain_delete_response.rb +23 -0
  108. data/test/domain/test_domain_info.rb +28 -0
  109. data/test/domain/test_domain_info_response.rb +107 -0
  110. data/test/domain/test_domain_renew.rb +39 -0
  111. data/test/domain/test_domain_renew_response.rb +32 -0
  112. data/test/domain/test_domain_transfer.rb +37 -0
  113. data/test/domain/test_domain_transfer_response.rb +112 -0
  114. data/test/domain/test_domain_update.rb +73 -0
  115. data/test/domain/test_domain_update_response.rb +23 -0
  116. data/test/fixtures/responses/contact/check.xml +27 -0
  117. data/test/fixtures/responses/contact/create.xml +19 -0
  118. data/test/fixtures/responses/contact/delete.xml +12 -0
  119. data/test/fixtures/responses/contact/info.xml +49 -0
  120. data/test/fixtures/responses/contact/transfer-query.xml +23 -0
  121. data/test/fixtures/responses/contact/transfer-request.xml +23 -0
  122. data/test/fixtures/responses/contact/update.xml +12 -0
  123. data/test/fixtures/responses/domain/check.xml +27 -0
  124. data/test/fixtures/responses/domain/create.xml +20 -0
  125. data/test/fixtures/responses/domain/delete.xml +12 -0
  126. data/test/fixtures/responses/domain/info-no-exDate.xml +38 -0
  127. data/test/fixtures/responses/domain/info.xml +39 -0
  128. data/test/fixtures/responses/domain/renew.xml +19 -0
  129. data/test/fixtures/responses/domain/transfer-query.xml +24 -0
  130. data/test/fixtures/responses/domain/transfer-request.xml +24 -0
  131. data/test/fixtures/responses/domain/update.xml +12 -0
  132. data/test/fixtures/responses/greeting.xml +25 -0
  133. data/test/fixtures/responses/host/check.xml +27 -0
  134. data/test/fixtures/responses/host/create.xml +19 -0
  135. data/test/fixtures/responses/host/delete.xml +12 -0
  136. data/test/fixtures/responses/host/info.xml +30 -0
  137. data/test/fixtures/responses/host/update.xml +12 -0
  138. data/test/helper.rb +89 -0
  139. data/test/host/test_host_check.rb +33 -0
  140. data/test/host/test_host_check_response.rb +38 -0
  141. data/test/host/test_host_create.rb +37 -0
  142. data/test/host/test_host_create_response.rb +33 -0
  143. data/test/host/test_host_delete.rb +28 -0
  144. data/test/host/test_host_delete_response.rb +23 -0
  145. data/test/host/test_host_info.rb +28 -0
  146. data/test/host/test_host_info_response.rb +72 -0
  147. data/test/host/test_host_update.rb +68 -0
  148. data/test/host/test_host_update_response.rb +23 -0
  149. data/test/requests/test_command_request.rb +16 -0
  150. data/test/requests/test_extension_request.rb +55 -0
  151. data/test/requests/test_hello_request.rb +15 -0
  152. data/test/support/schemas/all.xsd +21 -0
  153. data/test/support/schemas/contact-1.0.xsd +387 -0
  154. data/test/support/schemas/domain-1.0.xsd +432 -0
  155. data/test/support/schemas/epp-1.0.xsd +403 -0
  156. data/test/support/schemas/eppcom-1.0.xsd +93 -0
  157. data/test/support/schemas/host-1.0.xsd +240 -0
  158. data/test/test_client.rb +54 -0
  159. data/test/test_request.rb +15 -0
  160. data/test/test_server.rb +57 -0
  161. metadata +270 -91
  162. data/.document +0 -5
  163. data/README.rdoc +0 -17
  164. data/VERSION +0 -1
  165. data/lib/epp-client/hello_request.rb +0 -9
  166. data/test/test_epp-client.rb +0 -7
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Check < Command
6
+ def initialize(*names)
7
+ @names = names.flatten
8
+ end
9
+
10
+ def name
11
+ 'check'
12
+ end
13
+
14
+ def to_xml
15
+ node = super
16
+ @names.each do |name|
17
+ node << domain_node('name', name)
18
+ end
19
+ node
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class CheckResponse < Response
6
+ def available?(name)
7
+ availability[name]
8
+ end
9
+ def unavailable?(name)
10
+ !available?(name)
11
+ end
12
+
13
+ protected
14
+ def availability
15
+ @availability ||= nodes_for_xpath('//domain:name').inject({}) do |hash, node|
16
+ hash[node.content.strip] = node['avail'] == '1'
17
+ hash
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,92 @@
1
+ module EPP
2
+ module Domain
3
+ class Command
4
+ include XMLHelpers
5
+ attr_reader :namespaces
6
+
7
+ def set_namespaces(namespaces)
8
+ @namespaces = namespaces
9
+ end
10
+
11
+ def name
12
+ raise NotImplementedError, "#name must be implemented in subclasses"
13
+ end
14
+
15
+ def to_xml
16
+ @namespaces ||= {}
17
+ node = domain_node(name)
18
+
19
+ xattr = XML::Attr.new(node, "schemaLocation", SCHEMA_LOCATION)
20
+ xattr.namespaces.namespace = @namespaces['xsi'] || XML::Namespace.new(node, 'xsi', 'http://www.w3.org/2001/XMLSchema-instance')
21
+
22
+ node
23
+ end
24
+
25
+ protected
26
+ def domain_node(name, value = nil)
27
+ node = xml_node(name, value)
28
+ node.namespaces.namespace = domain_namespace(node)
29
+ node
30
+ end
31
+ def domain_namespace(node)
32
+ return @namespaces['domain'] if @namespaces.has_key?('domain')
33
+ @namespaces['domain'] = xml_namespace(node, 'domain', NAMESPACE)
34
+ end
35
+
36
+ def period_to_xml(period)
37
+ unit = period[-1,1]
38
+ val = period.to_i.to_s
39
+
40
+ p = domain_node('period', val)
41
+ p['unit'] = unit
42
+
43
+ p
44
+ end
45
+
46
+ def auth_info_to_xml(auth_info)
47
+ a = domain_node('authInfo')
48
+
49
+ if auth_info.has_key?(:pw)
50
+ a << pw = domain_node('pw', auth_info[:pw])
51
+ pw['roid'] = auth_info[:roid] if auth_info.has_key?(:roid)
52
+ elsif auth_info.has_key?(:ext)
53
+ a << domain_node('ext', auth_info[:ext])
54
+ end
55
+
56
+ a
57
+ end
58
+
59
+ def nameservers_to_xml(nameservers)
60
+ ns = domain_node('ns')
61
+
62
+ nameservers.each do |nameserver|
63
+ case nameserver
64
+ when String
65
+ ns << domain_node('hostObj', nameserver)
66
+ when Hash
67
+ ns << hostAttr = domain_node('hostAttr')
68
+ hostAttr << domain_node('hostName', nameserver[:name])
69
+ Array(nameserver[:ipv4]).each do |addr|
70
+ hostAttr << a = domain_node('hostAddr', addr)
71
+ a['ip'] = 'v4'
72
+ end
73
+ Array(nameserver[:ipv6]).each do |addr|
74
+ hostAttr << a = domain_node('hostAddr', addr)
75
+ a['ip'] = 'v6'
76
+ end
77
+ end
78
+ end
79
+
80
+ ns
81
+ end
82
+ def contacts_to_xml(node, contacts)
83
+ return if contacts.nil?
84
+ contacts.each do |type, roid|
85
+ next unless %w(admin tech billing).include?(type.to_s)
86
+ node << c = domain_node('contact', roid)
87
+ c['type'] = type.to_s
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Create < Command
6
+ #
7
+ # @param [String] name
8
+ # @param [String] period
9
+ # @param [Array<String,Hash>] nameservers
10
+ # @param [String] registrant
11
+ # @param [Hash<Symbol,String>] contacts
12
+ # @param [Hash<Symbol,String>] auth_info
13
+ #
14
+ # @option contacts [String] :admin
15
+ # @option contacts [String] :tech
16
+ # @option contacts [String] :billing
17
+ def initialize(name, options = {})
18
+ @name = name
19
+ @period = options.delete(:period) || '1y'
20
+ @nameservers = Array(options.delete(:nameservers))
21
+ @registrant = options.delete(:registrant)
22
+ @contacts = options.delete(:contacts)
23
+ @auth_info = options.delete(:auth_info)
24
+ end
25
+
26
+ def name
27
+ 'create'
28
+ end
29
+
30
+ def to_xml
31
+ node = super
32
+ node << domain_node('name', @name)
33
+ node << period_to_xml(@period) if @period
34
+
35
+ unless @nameservers.empty?
36
+ node << nameservers_to_xml(@nameservers)
37
+ end
38
+
39
+ node << domain_node('registrant', @registrant) if @registrant
40
+
41
+ contacts_to_xml(node, @contacts)
42
+
43
+ node << auth_info_to_xml(@auth_info) unless @auth_info.empty?
44
+
45
+ node
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class CreateResponse < Response
6
+ def name
7
+ @name ||= value_for_xpath('//domain:name')
8
+ end
9
+ def creation_date
10
+ @crdate ||= value_for_xpath('//domain:crDate') && Time.parse(value_for_xpath('//domain:crDate'))
11
+ end
12
+ def expiration_date
13
+ @exdate ||= value_for_xpath('//domain:exDate') && Time.parse(value_for_xpath('//domain:exDate'))
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Delete < Command
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def name
11
+ 'delete'
12
+ end
13
+
14
+ def to_xml
15
+ node = super
16
+ node << domain_node('name', @name)
17
+ node
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class DeleteResponse < Response
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Info < Command
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def name
11
+ 'info'
12
+ end
13
+
14
+ def to_xml
15
+ node = super
16
+ node << domain_node('name', @name)
17
+ node
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,66 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class InfoResponse < Response
6
+ def name
7
+ @name ||= value_for_xpath('//domain:name')
8
+ end
9
+ def roid
10
+ @roid ||= value_for_xpath('//domain:roid')
11
+ end
12
+ def status
13
+ @status ||= value_for_xpath('//domain:status/@s')
14
+ end
15
+ def registrant
16
+ @registrant ||= value_for_xpath('//domain:registrant')
17
+ end
18
+ def contacts
19
+ @contacts ||= nodes_for_xpath('//domain:contact').inject({}) do |hash, node|
20
+ hash[node['type'].to_s] = node.content.strip
21
+ hash
22
+ end
23
+ end
24
+ def nameservers
25
+ @nameservers ||= nodes_for_xpath('//domain:ns').map do |ns_node|
26
+ ns = ns_node.find('domain:hostAttr', namespaces).map do |hostAttr|
27
+ { 'name' => hostAttr.find('domain:name').first.content.strip,
28
+ 'ipv4' => hostAttr.find('domain:addr[@ip="v4"]').first.content.strip,
29
+ 'ipv6' => hostAttr.find('domain:addr[@ip="v6"]').first.content.strip }
30
+ end
31
+
32
+ ns + ns_node.find('domain:hostObj').map { |n| { 'name' => n.content.strip } }
33
+ end.flatten
34
+ end
35
+ def hosts
36
+ @hosts ||= values_for_xpath('//domain:host')
37
+ end
38
+ def client_id
39
+ @clid ||= value_for_xpath('//domain:clID')
40
+ end
41
+ def creator_id
42
+ @crid ||= value_for_xpath('//domain:crID')
43
+ end
44
+ def created_date
45
+ @crdate ||= value_for_xpath('//domain:crDate') && Time.parse(value_for_xpath('//domain:crDate'))
46
+ end
47
+ def updator_id
48
+ @upid ||= value_for_xpath('//domain:upID')
49
+ end
50
+ def updated_date
51
+ @update ||= value_for_xpath('//domain:upDate') && Time.parse(value_for_xpath('//domain:upDate'))
52
+ end
53
+ def expiration_date
54
+ @exdate ||= value_for_xpath('//domain:exDate') && Time.parse(value_for_xpath('//domain:exDate'))
55
+ end
56
+ def transfer_date
57
+ @trdate ||= value_for_xpath('//domain:trDate') && Time.parse(value_for_xpath('//domain:trDate'))
58
+ end
59
+ def auth_info
60
+ @auth_info ||= begin
61
+ { 'pw' => value_for_xpath('//domain:authInfo/domain:pw') }
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Renew < Command
6
+ def initialize(name, exp_date, period = nil)
7
+ @name, @exp_date = name, exp_date
8
+ @exp_date = Time.parse(exp_date) if exp_date.kind_of?(String)
9
+
10
+ @period_unit = period[-1,1]
11
+ @period_val = period.to_i.to_s
12
+
13
+ raise ArgumentError, "period suffix must either be 'm' or 'y'" unless %w(m y).include?(@period_unit)
14
+ end
15
+
16
+ def name
17
+ 'renew'
18
+ end
19
+
20
+ def to_xml
21
+ node = super
22
+ node << domain_node('name', @name)
23
+ node << domain_node('curExpDate', @exp_date.strftime("%Y-%m-%d"))
24
+
25
+ p = domain_node('period', @period_val)
26
+ p['unit'] = @period_unit
27
+
28
+ node << p
29
+
30
+ node
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path('../response', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class RenewResponse < Response
6
+ def name
7
+ @name ||= value_for_xpath('//domain:name')
8
+ end
9
+ def expiration_date
10
+ @date ||= value_for_xpath('//domain:exDate') && Time.parse(value_for_xpath('//domain:exDate'))
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ module EPP
2
+ module Domain
3
+ class Response
4
+ include ResponseHelper
5
+
6
+ def initialize(response)
7
+ @response = response
8
+ end
9
+
10
+ def method_missing(meth, *args, &block)
11
+ return super unless @response.respond_to?(meth)
12
+ @response.send(meth, *args, &block)
13
+ end
14
+
15
+ def respond_to_missing?(method, include_private)
16
+ @response.respond_to?(method, include_private)
17
+ end
18
+
19
+ unless RUBY_VERSION >= "1.9.2"
20
+ def respond_to?(method, include_private = false)
21
+ respond_to_missing?(method, include_private) || super
22
+ end
23
+ def method(sym)
24
+ respond_to_missing?(sym, true) ? @response.method(sym) : super
25
+ end
26
+ end
27
+
28
+ protected
29
+ def namespaces
30
+ {'domain' => NAMESPACE}
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../command', __FILE__)
2
+
3
+ module EPP
4
+ module Domain
5
+ class Transfer < Command
6
+ # @auth_info[:ext] should be an XML::Node with whatever is required
7
+ def initialize(name, period = nil, auth_info = {})
8
+ @name = name
9
+ @period = period
10
+ @auth_info = auth_info
11
+ end
12
+
13
+ def name
14
+ 'transfer'
15
+ end
16
+
17
+ def to_xml
18
+ node = super
19
+ node << domain_node('name', @name)
20
+ node << period_to_xml(@period) if @period
21
+ node << auth_info_to_xml(@auth_info) unless @auth_info.empty?
22
+
23
+ node
24
+ end
25
+ end
26
+ end
27
+ end