gandi_v5 0.3.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +56 -2
  4. data/.travis.yml +6 -1
  5. data/CHANGELOG.md +61 -0
  6. data/LICENSE.md +2 -6
  7. data/README.md +15 -9
  8. data/gandi_v5.gemspec +2 -2
  9. data/lib/gandi_v5.rb +40 -14
  10. data/lib/gandi_v5/data.rb +1 -2
  11. data/lib/gandi_v5/data/converter/integer.rb +26 -0
  12. data/lib/gandi_v5/domain.rb +13 -14
  13. data/lib/gandi_v5/email/forward.rb +2 -8
  14. data/lib/gandi_v5/email/mailbox.rb +57 -11
  15. data/lib/gandi_v5/email/slot.rb +11 -3
  16. data/lib/gandi_v5/live_dns.rb +0 -12
  17. data/lib/gandi_v5/live_dns/domain.rb +313 -29
  18. data/lib/gandi_v5/live_dns/domain/dnssec_key.rb +115 -0
  19. data/lib/gandi_v5/live_dns/domain/record.rb +81 -0
  20. data/lib/gandi_v5/live_dns/domain/snapshot.rb +107 -0
  21. data/lib/gandi_v5/live_dns/domain/tsig_key.rb +71 -0
  22. data/lib/gandi_v5/organization.rb +10 -0
  23. data/lib/gandi_v5/organization/customer.rb +90 -0
  24. data/lib/gandi_v5/sharing_space.rb +27 -0
  25. data/lib/gandi_v5/simple_hosting.rb +12 -0
  26. data/lib/gandi_v5/simple_hosting/instance.rb +242 -0
  27. data/lib/gandi_v5/simple_hosting/instance/application.rb +44 -0
  28. data/lib/gandi_v5/simple_hosting/instance/database.rb +19 -0
  29. data/lib/gandi_v5/simple_hosting/instance/language.rb +22 -0
  30. data/lib/gandi_v5/simple_hosting/instance/upgrade.rb +21 -0
  31. data/lib/gandi_v5/simple_hosting/instance/virtual_host.rb +187 -0
  32. data/lib/gandi_v5/simple_hosting/instance/virtual_host/linked_dns_zone.rb +74 -0
  33. data/lib/gandi_v5/version.rb +1 -1
  34. data/spec/.rubocop.yml +56 -2
  35. data/spec/fixtures/bodies/GandiV5_Domain/fetch.yml +8 -0
  36. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/fetch.yml +1 -2
  37. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/list_tsig.yml +3 -0
  38. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/nameservers.yml +3 -0
  39. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/fetch.yml +12 -0
  40. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/list.yml +9 -0
  41. data/spec/fixtures/bodies/{GandiV5_LiveDNS_Zone_Snapshot → GandiV5_LiveDNS_Domain_Snapshot}/fetch.yml +4 -3
  42. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_Snapshot/list.yml +5 -0
  43. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/fetch.yml +9 -0
  44. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/list.yml +4 -0
  45. data/spec/fixtures/bodies/GandiV5_Organization_Customer/list.yml +8 -0
  46. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance/fetch.yml +80 -0
  47. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance/list.yml +38 -0
  48. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance_VirtualHost/fetch.yml +26 -0
  49. data/spec/fixtures/bodies/GandiV5_SimpleHosting_Instance_VirtualHost/list.yml +18 -0
  50. data/spec/units/gandi_v5/data/converter/integer_spec.rb +16 -0
  51. data/spec/units/gandi_v5/domain_spec.rb +53 -43
  52. data/spec/units/gandi_v5/email/forward_spec.rb +5 -34
  53. data/spec/units/gandi_v5/email/mailbox_spec.rb +119 -37
  54. data/spec/units/gandi_v5/email/slot_spec.rb +10 -2
  55. data/spec/units/gandi_v5/live_dns/domain/dnssec_key_spec.rb +128 -0
  56. data/spec/units/gandi_v5/live_dns/{record_set_spec.rb → domain/record_spec.rb} +1 -1
  57. data/spec/units/gandi_v5/live_dns/domain/snapshot_spec.rb +101 -0
  58. data/spec/units/gandi_v5/live_dns/domain/tsig_key_spec.rb +78 -0
  59. data/spec/units/gandi_v5/live_dns/domain_spec.rb +297 -118
  60. data/spec/units/gandi_v5/live_dns_spec.rb +0 -12
  61. data/spec/units/gandi_v5/organization/customer_spec.rb +81 -0
  62. data/spec/units/gandi_v5/organization_spec.rb +14 -0
  63. data/spec/units/gandi_v5/sharing_space_spec.rb +4 -0
  64. data/spec/units/gandi_v5/simple_hosting/instance/application_spec.rb +37 -0
  65. data/spec/units/gandi_v5/simple_hosting/instance/database_spec.rb +4 -0
  66. data/spec/units/gandi_v5/simple_hosting/instance/language_spec.rb +4 -0
  67. data/spec/units/gandi_v5/simple_hosting/instance/upgrade_spec.rb +4 -0
  68. data/spec/units/gandi_v5/simple_hosting/instance/virtual_host/linked_dns_zone_spec.rb +50 -0
  69. data/spec/units/gandi_v5/simple_hosting/instance/virtual_host_spec.rb +199 -0
  70. data/spec/units/gandi_v5/simple_hosting/instance_spec.rb +182 -0
  71. data/spec/units/gandi_v5/simple_hosting_spec.rb +9 -0
  72. data/spec/units/gandi_v5_spec.rb +139 -30
  73. metadata +50 -31
  74. data/lib/gandi_v5/domain/sharing_space.rb +0 -21
  75. data/lib/gandi_v5/live_dns/has_zone_records.rb +0 -153
  76. data/lib/gandi_v5/live_dns/record_set.rb +0 -79
  77. data/lib/gandi_v5/live_dns/zone.rb +0 -160
  78. data/lib/gandi_v5/live_dns/zone/snapshot.rb +0 -81
  79. data/spec/features/domain_spec.rb +0 -45
  80. data/spec/features/livedns_domain_spec.rb +0 -8
  81. data/spec/features/livedns_zone_spec.rb +0 -45
  82. data/spec/features/mailbox_spec.rb +0 -18
  83. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/fetch.yml +0 -11
  84. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/list.yml +0 -11
  85. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/list.yml +0 -3
  86. data/spec/fixtures/vcr/Domain_features/List_domains.yml +0 -55
  87. data/spec/fixtures/vcr/Domain_features/Renew_domain.yml +0 -133
  88. data/spec/fixtures/vcr/LiveDNS_Domain_features/List_domains.yml +0 -32
  89. data/spec/fixtures/vcr/LiveDNS_Zone_features/List_zones.yml +0 -42
  90. data/spec/fixtures/vcr/LiveDNS_Zone_features/Make_and_save_snapshot.yml +0 -72
  91. data/spec/fixtures/vcr/LiveDNS_Zone_features/Save_zone_to_file.yml +0 -28
  92. data/spec/fixtures/vcr/Mailbox_features/List_mailboxes.yml +0 -39
  93. data/spec/units/gandi_v5/domain/sharing_space_spec.rb +0 -4
  94. data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +0 -66
  95. data/spec/units/gandi_v5/live_dns/zone_spec.rb +0 -347
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class LiveDNS
5
+ class Domain
6
+ # A DNSSEC key for a domain's DNS records.
7
+ # @!attribyte [r] uuid
8
+ # @return [String]
9
+ # @!attribyte [r] status
10
+ # @return [String]
11
+ # @!attribyte [r] fqdn
12
+ # @return [String]
13
+ # @!attribyte [r] algorithm_id
14
+ # @return [Integer]
15
+ # @!attribyte [r] algorithm_name
16
+ # @return [String]
17
+ # @!attribyte [r] deleted
18
+ # @return [Boolean]
19
+ # @!attribyte [r] ds
20
+ # @return [String]
21
+ # @!attribyte [r] flags
22
+ # @return [Integer]
23
+ # @!attribyte [r] fingerprint
24
+ # @return [String]
25
+ # @!attribyte [r] public_key
26
+ # @return [String]
27
+ # @!attribyte [r] tag
28
+ # @return [String]
29
+ class DnssecKey
30
+ include GandiV5::Data
31
+
32
+ members :status, :fqdn, :deleted, :ds, :flags, :fingerprint, :public_key,
33
+ :tag, :algorithm_name
34
+
35
+ member :uuid, gandi_key: 'id'
36
+ member :algorithm_id, gandi_key: 'algorithm'
37
+
38
+ # Delete this key.
39
+ # @return [String] The confirmation message from Gandi.
40
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
41
+ def delete
42
+ _response, data = GandiV5.delete url
43
+ self.deleted = true
44
+ data['message']
45
+ end
46
+
47
+ # Undelete this key.
48
+ # @return [String] The confirmation message from Gandi.
49
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
50
+ def undelete
51
+ _response, data = GandiV5.patch url, { deleted: false }.to_json
52
+ self.deleted = false
53
+ data['message']
54
+ end
55
+
56
+ # Check if this is a zone signing key
57
+ # @return [Boolean]
58
+ def zone_signing_key?
59
+ flags == 256
60
+ end
61
+
62
+ # Check if this is a key signing key
63
+ # @return [Boolean]
64
+ def key_signing_key?
65
+ flags == 257
66
+ end
67
+
68
+ # Create a new DNSSEC key for a zone.
69
+ # @param fqdn [String, #to_s] the fully qualified domain to create the key for.
70
+ # @param flags [Integer, :key_signing_key, :zone_signing_key] the key's flags.
71
+ # @return [GandiV5::LiveDNS::Domain::DnssecKey]
72
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
73
+ def self.create(fqdn, flags)
74
+ flags = 256 if flags == :zone_signing_key
75
+ flags = 257 if flags == :key_signing_key
76
+ fail ArgumentError, 'flags is invalid' unless flags.is_a?(Integer)
77
+
78
+ response, _data = GandiV5.post url(fqdn), { flags: flags }.to_json
79
+ fetch fqdn, response.headers[:location].split('/').last
80
+ end
81
+
82
+ # Get keys for a FQDN from Gandi.
83
+ # @param fqdn [String, #to_s] The fully qualified domain name to get the keys for.
84
+ # @return [Array<GandiV5::LiveDNS::Domain::DnssecKey>]
85
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
86
+ def self.list(fqdn)
87
+ _response, data = GandiV5.get url(fqdn)
88
+ data.map { |item| from_gandi item }
89
+ end
90
+
91
+ # Get DNSSEC key from Gandi.
92
+ # @param fqdn [String, #to_s] The fully qualified domain name the key was made for.
93
+ # @param uuid [String, #to_s] the UUID of the key to fetch.
94
+ # @return [GandiV5::LiveDNS::Domain::DnssecKey]
95
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
96
+ def self.fetch(fqdn, uuid)
97
+ _response, data = GandiV5.get url(fqdn, uuid)
98
+ from_gandi data
99
+ end
100
+
101
+ private
102
+
103
+ def url
104
+ "#{BASE}livedns/domains/#{CGI.escape fqdn}/keys/#{CGI.escape uuid}"
105
+ end
106
+
107
+ def self.url(fqdn, uuid = nil)
108
+ "#{BASE}livedns/domains/#{CGI.escape fqdn}/keys" +
109
+ (uuid ? "/#{CGI.escape uuid}" : '')
110
+ end
111
+ private_class_method :url
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class LiveDNS
5
+ class Domain
6
+ # A record set which comes from either a domain or zone.
7
+ # @!attribute [r] type
8
+ # @return [String]
9
+ # @!attribute [r] ttl
10
+ # @return [Integer]
11
+ # @!attribute [r] name
12
+ # @return [String]
13
+ # @!attribute [r] values
14
+ # @return [Array<String>]
15
+ class Record
16
+ include GandiV5::Data
17
+
18
+ member :type, gandi_key: 'rrset_type'
19
+ member :ttl, gandi_key: 'rrset_ttl', converter: GandiV5::Data::Converter::Integer
20
+ member :name, gandi_key: 'rrset_name'
21
+ member :values, gandi_key: 'rrset_values'
22
+
23
+ # Generate zone file lines for the record.
24
+ # @return [String]
25
+ def to_s
26
+ values.map do |value|
27
+ "#{name}\t#{ttl}\tIN\t#{type}\t#{value}"
28
+ end.join("\n")
29
+ end
30
+
31
+ GandiV5::LiveDNS::RECORD_TYPES.each do |t|
32
+ # Check the record type.
33
+ # @return [Boolean]
34
+ define_method "#{t.downcase}?" do
35
+ type.eql?(t)
36
+ end
37
+ end
38
+
39
+ # Check the TTL's value in seconds.
40
+ # @param number [Integer] the number of second(s) to check against.
41
+ # @return [Boolean]
42
+ def second?(number = 1)
43
+ ttl == number
44
+ end
45
+ alias seconds? second?
46
+
47
+ # Check the TTL's value in minutes.
48
+ # @param number [Integer] the number of minute(s) to check against.
49
+ # @return [Boolean]
50
+ def minute?(number = 1)
51
+ ttl == number * 60
52
+ end
53
+ alias minutes? minute?
54
+
55
+ # Check the TTL's value in hours.
56
+ # @param number [Integer] the number of hour(s) to check against.
57
+ # @return [Boolean]
58
+ def hour?(number = 1)
59
+ ttl == number * 3_600
60
+ end
61
+ alias hours? hour?
62
+
63
+ # Check the TTL's value in days.
64
+ # @param number [Integer] the number of day(s) to check against.
65
+ # @return [Boolean]
66
+ def day?(number = 1)
67
+ ttl == number * 86_400
68
+ end
69
+ alias days? day?
70
+
71
+ # Check the TTL's value in weeks.
72
+ # @param number [Integer] the number of week(s) to check against.
73
+ # @return [Boolean]
74
+ def week?(number = 1)
75
+ ttl == number * 604_800
76
+ end
77
+ alias weeks? day?
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class LiveDNS
5
+ class Domain
6
+ # A snapshot (backup) of a domain's DNS records.
7
+ # @!attribute [r] fqdn
8
+ # @return [String]
9
+ # @!attribute [r] uuid
10
+ # @return [String]
11
+ # @!attribute [r] name
12
+ # @return [String]
13
+ # @!attribute [r] created_at
14
+ # @return [Time]
15
+ # @!attribute [r] automatic
16
+ # @return [Boolean]
17
+ class Snapshot
18
+ include GandiV5::Data
19
+
20
+ members :name, :automatic, :fqdn
21
+ member :created_at, converter: GandiV5::Data::Converter::Time
22
+ member :uuid, gandi_key: 'id'
23
+ member(
24
+ :records,
25
+ gandi_key: 'zone_data',
26
+ converter: GandiV5::LiveDNS::Domain::Record,
27
+ array: true
28
+ )
29
+
30
+ alias snapshot_uuid uuid
31
+
32
+ # Delete this snapshot.
33
+ # @return [String] The confirmation message from Gandi.
34
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
35
+ def delete
36
+ _response, data = GandiV5.delete url
37
+ data['message']
38
+ end
39
+
40
+ # Update this snapshot.
41
+ # @param name [String, #to_s] new name for the snapshot.
42
+ # @return [String] The confirmation message from Gandi.
43
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
44
+ def update(name:)
45
+ _response, data = GandiV5.patch url, { name: name }.to_json
46
+ self.name = name
47
+ data['message']
48
+ end
49
+
50
+ # Get snapshot details for this FQDN from Gandi.
51
+ # @param fqdn [String, #to_s] The fully qualified domain name to get the snapshots for.
52
+ # @param page [#each<Integer, #to_s>] the page(s) of results to retrieve.
53
+ # If page is not provided keep querying until an empty list is returned.
54
+ # If page responds to .each then iterate until an empty list is returned.
55
+ # @param per_page [Integer, #to_s] (optional default 100) how many results to get per page.
56
+ # @param automatic [nil, Boolean] (optional) filter by automatic or manual snapshot.
57
+ # @return [Array<GandiV5::LiveDNS::Domain::Snapshot>]
58
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
59
+ def self.list(fqdn, page: (1..), per_page: 100, **params)
60
+ params.reject! { |_k, v| v.nil? }
61
+
62
+ snapshots = []
63
+ GandiV5.paginated_get(url(fqdn), page, per_page, params: params) do |data|
64
+ snapshots += data.map { |item| from_gandi item.merge(fqdn: fqdn) }
65
+ end
66
+ snapshots
67
+ end
68
+
69
+ # Get snapshot from Gandi.
70
+ # @param fqdn [String, #to_s] The fully qualified domain name the snapshot was made for.
71
+ # @param uuid [String, #to_s] the UUID of the snapshot to fetch.
72
+ # @return [GandiV5::LiveDNS::Domain::Snapshot]
73
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
74
+ def self.fetch(fqdn, uuid)
75
+ _response, data = GandiV5.get url(fqdn, uuid)
76
+ from_gandi data.merge(fqdn: fqdn)
77
+ end
78
+
79
+ # Get the records which makeup this snapshot (fetching from Gandi if required).
80
+ # @return [Array<GandiV5::LiveDNS::Domain::Record>]
81
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
82
+ def records
83
+ return @records unless @records.nil?
84
+
85
+ @records = fetch_records
86
+ end
87
+
88
+ private
89
+
90
+ def fetch_records
91
+ _response, data = GandiV5.get url
92
+ data.fetch('zone_data').map { |item| GandiV5::LiveDNS::Domain::Record.from_gandi item }
93
+ end
94
+
95
+ def url
96
+ "#{BASE}livedns/domains/#{CGI.escape fqdn}/snapshots/#{CGI.escape uuid}"
97
+ end
98
+
99
+ def self.url(fqdn, snapshot_uuid = nil)
100
+ "#{BASE}livedns/domains/#{CGI.escape fqdn}/snapshots" +
101
+ (snapshot_uuid ? "/#{CGI.escape snapshot_uuid}" : '')
102
+ end
103
+ private_class_method :url
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class LiveDNS
5
+ class Domain
6
+ # A Tsig key.
7
+ # @!attribyte [r] uuid
8
+ # @return [String]
9
+ # @!attribyte [r] name
10
+ # @return [String]
11
+ # @!attribyte [r] secret
12
+ # @return [String]
13
+ # @!attribyte [r] config_examples
14
+ # @return [Hash<Symbol -> String>]
15
+ class TsigKey
16
+ include GandiV5::Data
17
+
18
+ member :secret
19
+ member :uuid, gandi_key: 'id'
20
+ member :name, gandi_key: 'key_name'
21
+ member(
22
+ :config_examples,
23
+ gandi_key: 'config_samples',
24
+ converter: GandiV5::Data::Converter.new(
25
+ from_gandi: ->(value) { value.transform_keys(&:to_sym) },
26
+ to_gandi: ->(_value) { nil }
27
+ )
28
+ )
29
+
30
+ # Create a new DNSSEC key for a zone.
31
+ # @param sharing_id [nil, String, #to_s]
32
+ # @return [GandiV5::LiveDNS::Domain::DnssecKey]
33
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
34
+ def self.create(sharing_id = nil)
35
+ url_ = url
36
+ url_ += "?sharing_id=#{CGI.escape sharing_id}" if sharing_id
37
+
38
+ _response, data = GandiV5.post url_
39
+ fetch data.fetch('id')
40
+ end
41
+
42
+ # Get keys from Gandi.
43
+ # If you need the secret, fingerprint, public_key or tag attributes you'll need
44
+ # to use GandiV5::LiveDNS::Domain::DnssecKey.fetch on each item.
45
+ # @return [Array<GandiV5::LiveDNS::Domain::TsigKey>]
46
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
47
+ def self.list
48
+ _response, data = GandiV5.get url
49
+ data.map { |item| from_gandi item }
50
+ end
51
+
52
+ # Get Tsig key from Gandi.
53
+ # @param uuid [String, #to_s] the UUID of the key to fetch.
54
+ # @return [GandiV5::LiveDNS::Domain::TsigKey]
55
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
56
+ def self.fetch(uuid)
57
+ _response, data = GandiV5.get url(uuid)
58
+ from_gandi data
59
+ end
60
+
61
+ private
62
+
63
+ def self.url(uuid = nil)
64
+ "#{BASE}livedns/axfr/tsig" +
65
+ (uuid ? "/#{CGI.escape uuid}" : '')
66
+ end
67
+ private_class_method :url
68
+ end
69
+ end
70
+ end
71
+ end
@@ -50,6 +50,16 @@ class GandiV5
50
50
 
51
51
  alias organization_uuid uuid
52
52
 
53
+ # @see GandiV5::Organization::Customer.list
54
+ def customers(org_uuid, **params)
55
+ GandiV5::Organization::Customer.list(org_uuid, **params)
56
+ end
57
+
58
+ # @see GandiV5::Organization::Customer.create
59
+ def create_customer(org_uuid, **params)
60
+ GandiV5::Organization::Customer.create(org_uuid, **params)
61
+ end
62
+
53
63
  # Get information about the current authenticated user.
54
64
  # @see https://api.gandi.net/docs/organization#get-v5-organization-user-info
55
65
  # @return [GandiV5::Organization]
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class Organization
5
+ # A customer of a reseller organization
6
+ # @!attribute [r] id
7
+ # @return [String] The main identifier of the customer.
8
+ # Also known as sharing_id in many routes.
9
+ # @!attribute [r] email
10
+ # @return [String] Email of the customer.
11
+ # @!attribute [r] first_name
12
+ # @return [String] First name of the customer.
13
+ # @!attribute [r] last_name
14
+ # @return [String] Last name of the customer.
15
+ # @!attribute [r] name
16
+ # @return [String] Name of the customer.
17
+ # @!attribute [r] type
18
+ # @return [:individual, :company, :association, :publicbody]
19
+ # @!attribute [r] org_name
20
+ # @return [nil, String] Organization legal name of the customer..
21
+ class Customer
22
+ include GandiV5::Data
23
+
24
+ members :email, :name
25
+ member :uuid, gandi_key: 'id'
26
+ member :first_name, gandi_key: 'firstname'
27
+ member :last_name, gandi_key: 'lastname'
28
+ member :org_name, gandi_key: 'orgname'
29
+ member :type, converter: GandiV5::Data::Converter::Symbol
30
+
31
+ # Create a new customer for this organization.
32
+ # @see https://api.gandi.net/docs/organization/#post-v5-organization-organizations-id-customers
33
+ # @param org_uuid [String] UUID of the organization to create the customer for.
34
+ # @param firstname [String, #to_s] (required) Customer's first name.
35
+ # @param lastname [String, #to_s] (required) Customer's last name.
36
+ # @param type [String, #to_s] (required) Type of customer
37
+ # ("individual", "company", "association" or "publicbody").
38
+ # @param streetaddr [String, #to_s] (required) Customer's street address.
39
+ # @param city [String, #to_s] (required) Customer's city.
40
+ # @param country [String, #to_s] (required) Customer's country.
41
+ # @param email [String, #to_s] (required) Customer's email address.
42
+ # @param phone [String, #to_s] (required) Customer's phone number.
43
+ # @param fax [String, #to_s] (optional) Customer's fax number.
44
+ # @param streetaddr2 [String, #to_s] (optional) Customer's street address (2nd line).
45
+ # @param state [String, #to_s] (optional) Customer's state/province/region.
46
+ # @param zip [String, #to_s] (optional) Customer's postal/zip code.
47
+ # @param reference [String, #to_s] (optional)
48
+ # Optional text to display on the invoice, such as your own customer reference info.
49
+ # @param orgname [String, #to_s] (optional) Customer Organization's legal name.
50
+ # @return [nil]
51
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error
52
+ def self.create(org_uuid, **params)
53
+ %i[city country email firstname lastname phone streetaddr type].each do |attr|
54
+ fail ArgumentError, "missing keyword: #{attr}" unless params.key?(attr)
55
+ end
56
+ unless %w[individual company association publicbody].include?(params[:type].to_s)
57
+ fail ArgumentError, "invalid type: #{params[:type].inspect}"
58
+ end
59
+
60
+ _response, _data = GandiV5.post(url(org_uuid), params.to_json)
61
+ nil
62
+ end
63
+
64
+ # List organisation's customers.
65
+ # @see https://api.gandi.net/docs/organization/#get-v5-organization-organizations-id-customers
66
+ # @param org_uuid [String] UUID of the organization to fetch customers for.
67
+ # @param name [String, #to_s] (optional)
68
+ # filters the list by name, with optional patterns.
69
+ # e.g. "alice", "ali*", "*ice"
70
+ # @param permission [String, #to_s] (optional)
71
+ # filters the list by the permission the authenticated user has on
72
+ # that organization and products in it.
73
+ # @param sort_by [String, #to_s] (optional default "name") how to sort the list.
74
+ # @return [Array<GandiV5::Organization>]
75
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
76
+ def self.list(org_uuid, **params)
77
+ params['~name'] = params.delete(:name) if params.key?(:name)
78
+ _resp, data = GandiV5.get url(org_uuid), params: params
79
+ data.map { |organisation| from_gandi organisation }
80
+ end
81
+
82
+ private
83
+
84
+ def self.url(org_uuid)
85
+ "#{BASE}organization/organizations/#{org_uuid}/customers"
86
+ end
87
+ private_class_method :url
88
+ end
89
+ end
90
+ end