nominet-epp 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Delete Operation
4
+ module Delete
5
+ # Delete a domain from the registry
6
+ #
7
+ # @param [String] name Domain name
8
+ # @return [Boolean] success status
9
+ def delete(name)
10
+ resp = @client.delete do
11
+ domain('delete') do |node, ns|
12
+ node << XML::Node.new('name', name, ns)
13
+ end
14
+ end
15
+
16
+ resp.success?
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,53 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Fork Operation
4
+ module Fork
5
+ # Splits a selection of domains from one account into another.
6
+ #
7
+ # The returned hash contains the following keys
8
+ # - (String) +:roid+ -- New account ID
9
+ # - (String) +:name+ -- New account name
10
+ # - (String) +:crDate+ -- Date the account was created
11
+ # - (Hash) +:contact+ -- Contact details
12
+ #
13
+ # The +:contact+ hash contains the following keys
14
+ # - (String) +:roid+ -- Contact ID
15
+ # - (String) +:name+ -- Contact Name
16
+ # - (String) +:type+ -- Contact Type
17
+ # - (Integer) +:order+ -- Contact Order
18
+ #
19
+ # @param [String] account_num Account Number
20
+ # @param [String, ...] *names Domain names to fork from the account
21
+ # @return [false] fork failed
22
+ # @return [Hash] new account details
23
+ def fork(account_num, *names)
24
+ resp = @client.update do
25
+ account('fork') do |node, ns|
26
+ node << XML::Node.new('roid', account_num, ns)
27
+ names.each do |name|
28
+ node << XML::Node.new('domain-name', name, ns)
29
+ end
30
+ end
31
+ end
32
+
33
+ return false unless resp.success?
34
+
35
+ hash = {
36
+ :roid => node_value(resp.data, '//account:creData/account:roid'),
37
+ :name => node_value(resp.data, '//account:creData/account:name'),
38
+ :crDate => node_value(resp.data, '//account:creData/account:crDate'),
39
+ :contact => {
40
+ :roid => node_value(resp.data, '//account:creData/account:contact/contact:creData/contact:roid'),
41
+ :name => node_value(resp.data, '//account:creData/account:contact/contact:creData/contact:name')
42
+ }
43
+ }
44
+
45
+ contact = resp.data.find('//account:creData/account:contact', namespaces).first
46
+ hash[:contact][:type] = contact['type']
47
+ hash[:contact][:order] = contact['order']
48
+
49
+ hash
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,11 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Hello Operation
4
+ module Hello
5
+ # @return [Boolean] hello greeting returned
6
+ def hello
7
+ @client.hello # This should be a epp-client method
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,93 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Info Operation
4
+ module Info
5
+ # @param [Symbol] entity Type of entity to get information about
6
+ # @param [String] id Identifier of the entity
7
+ # @return [false] failed
8
+ # @return [Hash]
9
+ def info(entity, id)
10
+ raise ArgumentError, "entity must be :domain, :contact or :account" unless [:domain, :contact, :account].include?(entity)
11
+
12
+ resp = @client.info do
13
+ case entity
14
+ when :domain
15
+ domain('info') { |node, ns| node << XML::Node.new('name', id, ns) }
16
+ when :account
17
+ account('info') { |node, ns| node << XML::Node.new('roid', id, ns) }
18
+ when :contact
19
+ contact('info') { |node, ns| node << XML::Node.new('roid', id, ns) }
20
+ end
21
+ end
22
+
23
+ return false unless resp.success?
24
+ self.send(:"info_#{entity}", resp.data)
25
+ end
26
+
27
+ private
28
+ # @param [XML::Node] data Domain data
29
+ # @return [Hash]
30
+ def info_domain(data)
31
+ hash = {}
32
+ data.find('//domain:infData', namespaces).first.children.reject{|n| n.empty?}.each do |node|
33
+ key = node.name.gsub('-', '_').to_sym
34
+ case node.name
35
+ when 'account'
36
+ hash[:account] = info_account(node)
37
+ when 'ns'
38
+ hash[:ns] = node.find('domain:host', namespaces).map do |hostnode|
39
+ { :name => node_value(hostnode, 'domain:hostName'),
40
+ :v4 => node_value(hostnode, 'domain:hostAddr[@ip="v4"]'),
41
+ :v6 => node_value(hostnode, 'domain:hostAddr[@ip="v6"]') }.reject{|k,v| v.nil?}
42
+ end
43
+ when /date/i
44
+ hash[key] = Time.parse(node.content.strip)
45
+ else
46
+ hash[key] = node.content.strip
47
+ end
48
+ end
49
+ hash
50
+ end
51
+
52
+ # @param [XML::Node] data Account data
53
+ # @return [Hash]
54
+ def info_account(data)
55
+ hash = {}
56
+ data.find('//account:infData', namespaces).first.children.reject{|n| n.empty?}.each do |node|
57
+ key = node.name.gsub('-', '_').to_sym
58
+ case node.name
59
+ when 'addr'
60
+ hash[:addr] = {}
61
+ node.children.reject{|n| n.empty?}.each do |n|
62
+ hash[:addr][n.name.to_sym] = n.content.strip
63
+ end
64
+ when 'contact'
65
+ hash[:contacts] ||= Array.new
66
+ hash[:contacts] << info_contact(node)
67
+ hash[:contacts].last[:type] = node['type']
68
+ hash[:contacts].last[:order] = node['order']
69
+ when /date/i
70
+ hash[key] = Time.parse(node.content.strip)
71
+ else
72
+ hash[key] = node.content.strip
73
+ end
74
+ end
75
+ hash
76
+ end
77
+
78
+ # @param [XML::Node] data Contact data
79
+ # @return [Hash]
80
+ def info_contact(data)
81
+ hash = {}
82
+ data.find('//contact:infData', namespaces).first.children.reject{|n| n.empty?}.each do |node|
83
+ if node.name =~ /date/i
84
+ hash[node.name.to_sym] = Time.parse(node.content.strip)
85
+ else
86
+ hash[node.name.to_sym] = node.content.strip
87
+ end
88
+ end
89
+ hash
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,83 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP List Operatons
4
+ module List
5
+ # Obtain a list of domains, and optionally their details, which either
6
+ # expire or were registered in the month given.
7
+ #
8
+ # @param [Symbol] type Listing type, either +:expiry+ or +:month+
9
+ # @param [String, #strftime] date Date of either expiry or registration to list
10
+ # @param [String] fields Verbosity of the response, either 'none' or 'all'
11
+ # @raise [ArgumentError] type must be +:expiry+ or +:month+
12
+ # @return [nil] list failed
13
+ # @return [Array<String>] list of domains
14
+ # @return [Array<Hash>] list of domains with details
15
+ def list(type, date, fields = 'none')
16
+ raise ArgumentError, "type must be :expiry or :month" unless [:expiry, :month].include?(type)
17
+
18
+ date = date.strftime("%Y-%m") if date.respond_to?(:strftime)
19
+ resp = @client.info do
20
+ domain('list') do |node, ns|
21
+ node << XML::Node.new(type, date, ns)
22
+ node << XML::Node.new('fields', fields, ns)
23
+ end
24
+ end
25
+
26
+ return nil unless resp.success?
27
+
28
+ if fields == 'none'
29
+ resp.data.find('//domain:name', namespaces).map do |node|
30
+ node.content.strip
31
+ end
32
+ else
33
+ resp.data.find('//domain:infData', namespaces).map do |infData|
34
+ hash = {}
35
+ infData.children.reject{|n| n.empty?}.each do |node|
36
+ key = node.name.gsub('-', '_').to_sym
37
+ case node.name
38
+ when 'account'
39
+ hash[:account] = info_account(node)
40
+ when 'ns'
41
+ hash[:ns] = node.find('domain:host', namespaces).map do |hostnode|
42
+ { :name => node_value(hostnode, 'domain:hostName'),
43
+ :v4 => node_value(hostnode, 'domain:hostAddr[@ip="v4"]'),
44
+ :v6 => node_value(hostnode, 'domain:hostAddr[@ip="v6"]') }.reject{|k,v| v.nil?}
45
+ end
46
+ when /date/i
47
+ hash[key] = Time.parse(node.content.strip)
48
+ else
49
+ hash[key] = node.content.strip
50
+ end
51
+ end
52
+ hash
53
+ end
54
+ end
55
+ end
56
+
57
+ # list of all tags that accept tag changes along with their handshake settings
58
+ #
59
+ # The returned array of hashes contain the following keys
60
+ # - (String) +:registrar_tag+ -- TAG name
61
+ # - (String) +:name+ -- Name of the TAG owner
62
+ # - (String) +:trad_name+ -- TAG trading name
63
+ # - (BOOL) +:handshake+ -- Whether the TAG accepts handshakes
64
+ #
65
+ # @return [false] failure
66
+ # @return [Array<Hash>] tag details
67
+ def tag_list
68
+ resp = @client.info do
69
+ tag('list')
70
+ end
71
+
72
+ return false unless resp.success?
73
+
74
+ resp.data.find('//tag:infData', namespaces).map do |node|
75
+ { :registrar_tag => node_value(node, 'tag:registrar-tag'),
76
+ :name => node_value(node, 'tag:name'),
77
+ :trad_name => node_value(node, 'tag:trad-name'),
78
+ :handshake => node_value(node, 'tag:handshake') == 'Y' }
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,56 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Lock Operation
4
+ module Lock
5
+ # Lock domain or account 'investigation' or 'opt-out'
6
+ #
7
+ # @param [Symbol] entity Entity to lock
8
+ # @param [String] type Type of lock to set
9
+ # @param [String] id Domain name or account ID
10
+ # @raise [ArgumentError] entity is not +:domain+ or +:account+
11
+ # @raise [ArgumentError] type is not 'investigation' or 'opt-out'
12
+ # @return [Boolean] locking successful
13
+ def lock(entity, type, id)
14
+ raise ArgumentError, "entity must be :domain or :account" unless [:domain, :account].include?(entity)
15
+ raise ArgumentError, "type must be 'investigation' or 'opt-out'" unless %w(investigation opt-out).include?(type)
16
+
17
+ resp = @client.update do
18
+ case type
19
+ when 'investigation'
20
+ lock_investigation(entity, id)
21
+ when 'opt-out'
22
+ lock_opt_out(entity, id)
23
+ end
24
+ end
25
+
26
+ return resp.success?
27
+ end
28
+ private
29
+ # Create +account:lock+ XML element for opt-out lock
30
+ # @param [Symbol] entity Entity to set opt out lock on
31
+ # @param [String] id Domain name or Account ID to lock
32
+ # @return [XML::Node] +account:lock+ element
33
+ def lock_opt_out(entity, id)
34
+ account('lock') do |node, ns|
35
+ node['type'] = 'opt-out'
36
+ node << XML::Node.new((entity == :domain ? 'domain-name' : 'roid'), id, ns)
37
+ end
38
+ end
39
+
40
+ # Create +lock+ XML element for investigation lock
41
+ #
42
+ # We don't support 'investigation' on account:domain-name as this ability
43
+ # is already provided via domain:name
44
+ #
45
+ # @param [Symbol] entity Entity to set investigation lock on
46
+ # @param [String] id Domain name or account ID to set lock on
47
+ # @return [XML::Node] +lock+ element
48
+ def lock_investigation(entity, id)
49
+ self.send(entity, 'lock') do |node, ns|
50
+ node['type'] = 'investigation'
51
+ node << XML::Node.new((entity == :domain ? 'name' : 'roid'), id, ns)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,41 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Merge Operation
4
+ module Merge
5
+ # Merge accounts or domains into an Account
6
+ #
7
+ # @param [String] target Account ID to merge into
8
+ # @param [Hash] sources Account IDs to merge into the target
9
+ # @option sources [Array] :accounts Account numbers to merge
10
+ # @option sources [Array] :names Account names to merge
11
+ # @option sources [Array] :domains Domain names to merge
12
+ # @return [false] merge failed
13
+ # @return [Response] merge succeded
14
+ def merge(target, sources = {})
15
+ resp = @client.update do
16
+ account('merge') do |node, ns|
17
+ node << XML::Node.new('roid', target, ns)
18
+
19
+ (sources[:accounts] || []).each do |acct|
20
+ n = XML::Node.new('roid', acct, ns)
21
+ n['source'] = 'y'
22
+ node << n
23
+ end
24
+
25
+ (sources[:names] || []).each do |name|
26
+ node << XML::Node.new('name', name, ns)
27
+ end
28
+
29
+ (sources[:domains] || []).each do |domain|
30
+ node << XML::Node.new('domain-name', domain, ns)
31
+ end
32
+ end
33
+ end
34
+
35
+ return false unless resp.success?
36
+
37
+ resp # Need to test this to see what gets returned
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,38 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Poll Operation
4
+ module Poll
5
+ # Poll the EPP server for events
6
+ #
7
+ # @yield [data] process data if messages to poll
8
+ # @yieldparam [XML::Node] data Response data
9
+ # @return [nil] no messages to handle
10
+ # @return [Boolean] ack successful
11
+ # @see ack
12
+ def poll
13
+ resp = @client.poll do |poll|
14
+ poll['op'] = 'req'
15
+ end
16
+
17
+ return if resp.code != 1301 || resp.msgQ['count'] == '0'
18
+
19
+ yield resp.data
20
+
21
+ ack(resp.msgQ['id'])
22
+ end
23
+
24
+ # Acknowledges a polled message ID
25
+ #
26
+ # @param [String] msgID Message ID to acknowledge
27
+ # @return [Boolean] ack successful
28
+ def ack(msgID)
29
+ resp = @client.poll do |poll|
30
+ poll['op'] = 'ack'
31
+ poll['msgID'] = msgID
32
+ end
33
+
34
+ return resp.success?
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ module NominetEPP
2
+ module Operations
3
+ # EPP Renew Operation
4
+ module Renew
5
+ # Renew a domain name
6
+ #
7
+ # @param [String] name Domain name to renew
8
+ # @param [String] period Length of time to renew for. Currently has to be '2y'.
9
+ # @raise [ArgumentError] invalid period specified
10
+ # @raise [RuntimeError] renewed domain name does not match +name+
11
+ # @return [false] renewal failed
12
+ # @return [Time] domain expiration date
13
+ def renew(name, period = '2y')
14
+ period = '2y' # reset period to 2 years as nominet don't currently support other options
15
+
16
+ unit = period[-1..1]
17
+ num = period.to_i.to_s
18
+
19
+ raise ArgumentError, "period suffix must either be 'm' or 'y'" unless %w(m y).include?(unit)
20
+
21
+ resp = @client.renew do
22
+ domain('renew') do |node, ns|
23
+ node << XML::Node.new('name', name, ns)
24
+ p = XML::Node.new('period', num, ns);
25
+ p['unit'] = unit
26
+ node << p
27
+ end
28
+ end
29
+
30
+ return false unless resp.success?
31
+
32
+ renName = node_value(resp.data, '//domain:renData/domain:name')
33
+ renExp = node_value(resp.data, '//domain:renData/domain:exDate')
34
+
35
+ raise "Renewed name #{renName} does not match #{name}" if renName != name
36
+ return Time.parse(renExp)
37
+ end
38
+ end
39
+ end
40
+ end