epp-client 0.0.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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