gandi_v5 0.2.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +13 -3
  4. data/.travis.yml +15 -1
  5. data/CHANGELOG.md +63 -0
  6. data/FUNDING.yml +10 -0
  7. data/LICENSE.md +2 -6
  8. data/README.md +16 -21
  9. data/gandi_v5.gemspec +3 -2
  10. data/lib/gandi_v5.rb +64 -24
  11. data/lib/gandi_v5/billing.rb +0 -2
  12. data/lib/gandi_v5/billing/info.rb +0 -2
  13. data/lib/gandi_v5/data.rb +1 -4
  14. data/lib/gandi_v5/data/converter.rb +0 -4
  15. data/lib/gandi_v5/data/converter/integer.rb +26 -0
  16. data/lib/gandi_v5/domain.rb +167 -28
  17. data/lib/gandi_v5/domain/availability.rb +0 -3
  18. data/lib/gandi_v5/domain/availability/product.rb +0 -3
  19. data/lib/gandi_v5/domain/live_dns.rb +42 -0
  20. data/lib/gandi_v5/domain/renewal_information.rb +0 -3
  21. data/lib/gandi_v5/domain/sharing_space.rb +10 -2
  22. data/lib/gandi_v5/email.rb +0 -4
  23. data/lib/gandi_v5/email/forward.rb +102 -0
  24. data/lib/gandi_v5/email/mailbox.rb +57 -13
  25. data/lib/gandi_v5/email/slot.rb +11 -3
  26. data/lib/gandi_v5/error.rb +0 -2
  27. data/lib/gandi_v5/live_dns.rb +0 -16
  28. data/lib/gandi_v5/live_dns/domain.rb +221 -80
  29. data/lib/gandi_v5/live_dns/domain/dnssec_key.rb +115 -0
  30. data/lib/gandi_v5/live_dns/domain/record.rb +81 -0
  31. data/lib/gandi_v5/live_dns/domain/snapshot.rb +107 -0
  32. data/lib/gandi_v5/live_dns/domain/tsig_key.rb +71 -0
  33. data/lib/gandi_v5/organization.rb +38 -5
  34. data/lib/gandi_v5/organization/customer.rb +90 -0
  35. data/lib/gandi_v5/version.rb +1 -1
  36. data/spec/.rubocop.yml +9 -2
  37. data/spec/fixtures/bodies/GandiV5_Billing/{info.yaml → info.yml} +0 -0
  38. data/spec/fixtures/bodies/GandiV5_Domain/{get.yaml → fetch.yml} +8 -0
  39. data/spec/fixtures/bodies/GandiV5_Domain/{fetch_contacts.yaml → fetch_contacts.yml} +0 -0
  40. data/spec/fixtures/bodies/GandiV5_Domain/fetch_glue_records.yml +7 -0
  41. data/spec/fixtures/bodies/GandiV5_Domain/fetch_livedns.yml +6 -0
  42. data/spec/fixtures/bodies/GandiV5_Domain/fetch_name_servers.yml +2 -0
  43. data/spec/fixtures/bodies/GandiV5_Domain/{renewal_info.yaml → fetch_renewal_info.yml} +0 -3
  44. data/spec/fixtures/bodies/GandiV5_Domain/{restore_info.yaml → fetch_restore_info.yml} +0 -0
  45. data/spec/fixtures/bodies/GandiV5_Domain/{list.yaml → list.yml} +1 -0
  46. data/spec/fixtures/bodies/GandiV5_Domain_Availability/{fetch.yaml → fetch.yml} +0 -0
  47. data/spec/fixtures/bodies/GandiV5_Domain_TLD/{fetch.yaml → fetch.yml} +0 -0
  48. data/spec/fixtures/bodies/GandiV5_Domain_TLD/{list.yaml → list.yml} +0 -0
  49. data/spec/fixtures/bodies/GandiV5_Email_Forward/list.yml +6 -0
  50. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{get.yaml → fetch.yml} +0 -0
  51. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{list.yaml → list.yml} +0 -0
  52. data/spec/fixtures/bodies/GandiV5_Email_Slot/{get.yaml → fetch.yml} +0 -0
  53. data/spec/fixtures/bodies/GandiV5_Email_Slot/{list.yaml → list.yml} +0 -0
  54. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/fetch.yml +3 -0
  55. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{list.yaml → list.yml} +0 -0
  56. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/list_tsig.yml +3 -0
  57. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/nameservers.yml +3 -0
  58. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/fetch.yml +12 -0
  59. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_DnssecKey/list.yml +9 -0
  60. data/spec/fixtures/bodies/{GandiV5_LiveDNS_Zone_Snapshot/fetch.yaml → GandiV5_LiveDNS_Domain_Snapshot/fetch.yml} +4 -3
  61. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_Snapshot/list.yml +5 -0
  62. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/fetch.yml +9 -0
  63. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain_TsigKey/list.yml +4 -0
  64. data/spec/fixtures/bodies/GandiV5_Organization/{get.yaml → fetch.yml} +0 -0
  65. data/spec/fixtures/bodies/GandiV5_Organization/list.yml +7 -0
  66. data/spec/fixtures/bodies/GandiV5_Organization_Customer/list.yml +8 -0
  67. data/spec/spec_helper.rb +2 -2
  68. data/spec/units/gandi_v5/billing_spec.rb +2 -2
  69. data/spec/units/gandi_v5/data/converter/integer_spec.rb +16 -0
  70. data/spec/units/gandi_v5/domain/availability_spec.rb +1 -1
  71. data/spec/units/gandi_v5/domain/live_dns_spec.rb +45 -0
  72. data/spec/units/gandi_v5/domain/tld_spec.rb +2 -2
  73. data/spec/units/gandi_v5/domain_spec.rb +294 -65
  74. data/spec/units/gandi_v5/email/forward_spec.rb +92 -0
  75. data/spec/units/gandi_v5/email/mailbox_spec.rb +122 -40
  76. data/spec/units/gandi_v5/email/slot_spec.rb +13 -5
  77. data/spec/units/gandi_v5/live_dns/domain/dnssec_key_spec.rb +128 -0
  78. data/spec/units/gandi_v5/live_dns/{record_set_spec.rb → domain/record_spec.rb} +1 -1
  79. data/spec/units/gandi_v5/live_dns/domain/snapshot_spec.rb +101 -0
  80. data/spec/units/gandi_v5/live_dns/domain/tsig_key_spec.rb +78 -0
  81. data/spec/units/gandi_v5/live_dns/domain_spec.rb +299 -120
  82. data/spec/units/gandi_v5/live_dns_spec.rb +0 -12
  83. data/spec/units/gandi_v5/organization/customer_spec.rb +81 -0
  84. data/spec/units/gandi_v5/organization_spec.rb +52 -1
  85. data/spec/units/gandi_v5_spec.rb +139 -30
  86. metadata +68 -95
  87. data/doc/GandiV5.html +0 -1183
  88. data/doc/GandiV5/Billing.html +0 -293
  89. data/doc/GandiV5/Billing/Info.html +0 -641
  90. data/doc/GandiV5/Billing/Info/Prepaid.html +0 -817
  91. data/doc/GandiV5/Data.html +0 -785
  92. data/doc/GandiV5/Data/ClassMethods.html +0 -223
  93. data/doc/GandiV5/Data/Converter.html +0 -433
  94. data/doc/GandiV5/Data/Converter/ArrayOf.html +0 -413
  95. data/doc/GandiV5/Data/Converter/Symbol.html +0 -322
  96. data/doc/GandiV5/Data/Converter/Time.html +0 -330
  97. data/doc/GandiV5/Domain.html +0 -16847
  98. data/doc/GandiV5/Domain/AutoRenew.html +0 -1237
  99. data/doc/GandiV5/Domain/Availability.html +0 -1020
  100. data/doc/GandiV5/Domain/Availability/Product.html +0 -988
  101. data/doc/GandiV5/Domain/Availability/Product/Period.html +0 -220
  102. data/doc/GandiV5/Domain/Availability/Product/Price.html +0 -1031
  103. data/doc/GandiV5/Domain/Availability/Tax.html +0 -440
  104. data/doc/GandiV5/Domain/Contact.html +0 -4459
  105. data/doc/GandiV5/Domain/Contract.html +0 -520
  106. data/doc/GandiV5/Domain/Dates.html +0 -1313
  107. data/doc/GandiV5/Domain/RenewalInformation.html +0 -1147
  108. data/doc/GandiV5/Domain/RestoreInformation.html +0 -339
  109. data/doc/GandiV5/Domain/SharingSpace.html +0 -437
  110. data/doc/GandiV5/Domain/TLD.html +0 -1565
  111. data/doc/GandiV5/Email.html +0 -144
  112. data/doc/GandiV5/Email/Mailbox.html +0 -6307
  113. data/doc/GandiV5/Email/Mailbox/Responder.html +0 -1560
  114. data/doc/GandiV5/Email/Offer.html +0 -514
  115. data/doc/GandiV5/Email/Slot.html +0 -4244
  116. data/doc/GandiV5/Error.html +0 -151
  117. data/doc/GandiV5/Error/GandiError.html +0 -270
  118. data/doc/GandiV5/LiveDNS.html +0 -300
  119. data/doc/GandiV5/LiveDNS/Domain.html +0 -2984
  120. data/doc/GandiV5/LiveDNS/RecordSet.html +0 -1593
  121. data/doc/GandiV5/LiveDNS/Zone.html +0 -8891
  122. data/doc/GandiV5/LiveDNS/Zone/Snapshot.html +0 -1556
  123. data/doc/GandiV5/Organization.html +0 -2341
  124. data/doc/_index.html +0 -474
  125. data/doc/class_list.html +0 -51
  126. data/doc/css/common.css +0 -1
  127. data/doc/css/full_list.css +0 -58
  128. data/doc/css/style.css +0 -496
  129. data/doc/file.README.html +0 -175
  130. data/doc/file_list.html +0 -56
  131. data/doc/frames.html +0 -17
  132. data/doc/index.html +0 -175
  133. data/doc/js/app.js +0 -303
  134. data/doc/js/full_list.js +0 -216
  135. data/doc/js/jquery.js +0 -4
  136. data/doc/method_list.html +0 -2427
  137. data/doc/top-level-namespace.html +0 -110
  138. data/lib/gandi_v5/live_dns/record_set.rb +0 -79
  139. data/lib/gandi_v5/live_dns/zone.rb +0 -305
  140. data/lib/gandi_v5/live_dns/zone/snapshot.rb +0 -81
  141. data/spec/features/domain_spec.rb +0 -45
  142. data/spec/features/livedns_domain_spec.rb +0 -8
  143. data/spec/features/livedns_zone_spec.rb +0 -45
  144. data/spec/features/mailbox_spec.rb +0 -18
  145. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/get.yaml +0 -4
  146. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/get.yaml +0 -11
  147. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/list.yaml +0 -11
  148. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/list.yaml +0 -3
  149. data/spec/fixtures/vcr/Domain_features/List_domains.yml +0 -54
  150. data/spec/fixtures/vcr/Domain_features/Renew_domain.yml +0 -133
  151. data/spec/fixtures/vcr/LiveDNS_Domain_features/List_domains.yml +0 -32
  152. data/spec/fixtures/vcr/LiveDNS_Zone_features/List_zones.yml +0 -42
  153. data/spec/fixtures/vcr/LiveDNS_Zone_features/Make_and_save_snapshot.yml +0 -72
  154. data/spec/fixtures/vcr/LiveDNS_Zone_features/Save_zone_to_file.yml +0 -28
  155. data/spec/fixtures/vcr/Mailbox_features/List_mailboxes.yml +0 -39
  156. data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +0 -66
  157. data/spec/units/gandi_v5/live_dns/zone_spec.rb +0 -347
@@ -1,15 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'domain/auto_renew'
4
- require_relative 'domain/availability'
5
- require_relative 'domain/contact'
6
- require_relative 'domain/contract'
7
- require_relative 'domain/dates'
8
- require_relative 'domain/renewal_information'
9
- require_relative 'domain/restore_information'
10
- require_relative 'domain/sharing_space'
11
- require_relative 'domain/tld'
12
-
13
3
  class GandiV5
14
4
  # Gandi Domain Management API.
15
5
  # @see https://api.gandi.net/docs/domains
@@ -221,10 +211,13 @@ class GandiV5
221
211
  # @param duration [Integer, #to_s] how long to renew for (in years).
222
212
  # @return [String] confirmation message from Gandi.
223
213
  # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
224
- def renew_for(duration = 1)
214
+ def renew_for(duration = 1, sharing_id: nil, dry_run: false)
225
215
  body = { duration: duration }.to_json
226
- _response, data = GandiV5.post url('renew'), body
227
- data['message']
216
+ url_ = url('renew')
217
+ url_ = sharing_id ? "#{url_}?sharing_id=#{sharing_id}" : url_
218
+
219
+ _response, data = GandiV5.post(url_, body, 'Dry-Run': dry_run ? 1 : 0)
220
+ dry_run ? data : data['message']
228
221
  end
229
222
 
230
223
  # Restoration information for the domain.
@@ -280,10 +273,163 @@ class GandiV5
280
273
  .prices.first
281
274
  end
282
275
 
276
+ # LiveDNS information for the domain.
277
+ # @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-livedns
278
+ # @return [GandiV5::Domain::LiveDNS]
279
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
280
+ def livedns
281
+ @livedns ||= fetch_livedns
282
+ end
283
+
284
+ # Requery Gandi for the domain's LiveDNS information.
285
+ # @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-livedns
286
+ # @return [GandiV5::Domain::LiveDNS]
287
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
288
+ def fetch_livedns
289
+ _response, data = GandiV5.get url('livedns')
290
+ @livedns = GandiV5::Domain::LiveDNS.from_gandi data
291
+ @name_server = @livedns.current
292
+ @name_servers = @livedns.name_servers
293
+ @livedns
294
+ end
295
+
296
+ # Enable LiveDNS for the domain.
297
+ # If you want to disable LiveDNS, change the nameservers.
298
+ # Please note that if the domain is on the classic Gandi DNS,
299
+ # this will also perform a copy of all existing records immediately afterwards.
300
+ # @see https://api.gandi.net/docs/domains#post-v5-domain-domains-domain-livedns
301
+ # @return [String] confirmation message from Gandi.
302
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
303
+ def enable_livedns
304
+ _response, data = GandiV5.post url('livedns')
305
+ data['message']
306
+ end
307
+
308
+ # Name servers for the domain.
309
+ # @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-nameservers
310
+ # @return [Array<String>]
311
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
312
+ def name_servers
313
+ @name_servers ||= fetch_name_servers
314
+ end
315
+
316
+ # Requery Gandi for the domain's name servers.
317
+ # @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-nameservers
318
+ # @return [Array<String>]
319
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
320
+ def fetch_name_servers
321
+ _response, data = GandiV5.get url('nameservers')
322
+ @name_servers = data
323
+ end
324
+
325
+ # Update name servers in Gandi.
326
+ # @see https://api.gandi.net/docs/domains#put-v5-domain-domains-domain-nameservers
327
+ # @param nameservers [Array<String>] the name servers to use.
328
+ # @return [String] confirmation message from Gandi.
329
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
330
+ def update_name_servers(nameservers)
331
+ _response, data = GandiV5.put url('nameservers'), { 'nameservers' => nameservers }.to_json
332
+ @name_servers = nameservers
333
+ data['message']
334
+ end
335
+
336
+ # Glue records for the domain.
337
+ # @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-hosts
338
+ # @return [Hash<String => Array<String>>] name to list of IPs
339
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
340
+ def glue_records
341
+ @glue_records ||= fetch_glue_records
342
+ end
343
+
344
+ # Requery Gandi for the domain's glue records.
345
+ # @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-hosts
346
+ # @return [Hash<String => Array<String>>] name to list of IPs
347
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
348
+ def fetch_glue_records
349
+ _response, data = GandiV5.get url('hosts')
350
+ @glue_records = data.map { |record| record.values_at('name', 'ips') }.to_h
351
+ end
352
+
353
+ # Add a new glue record to the domain in Gandi.
354
+ # @see https://api.gandi.net/docs/domains#post-v5-domain-domains-domain-hosts
355
+ # @param name [String] the DNS name (excluding FQDN) for the glue record to add (e.g. 'ns1').
356
+ # @param ips [Array<String>] the IPs for the name.
357
+ # @return [String] confirmation message from Gandi.
358
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
359
+ def add_glue_record(name, *ips)
360
+ _response, data = GandiV5.post url('hosts'), { 'name' => name, 'ips' => ips }.to_json
361
+ @glue_records ||= {}
362
+ @glue_records[name] = ips
363
+ data['message']
364
+ end
365
+
366
+ # Get a specific glue record for the domain.
367
+ # @see https://api.gandi.net/docs/domains#get-v5-domain-domains-domain-hosts
368
+ # @param name [String] the DNS name (excluding FQDN) for the glue record to add (e.g. 'ns1').
369
+ # @return [Hash<String => Array<String>>] name to list of IPs
370
+ # @return [nil] name was not found
371
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
372
+ def glue_record(name)
373
+ records = @glue_records.key?(name) ? @glue_records : fetch_glue_records
374
+ records.key?(name) ? records.select { |k, _v| k == name } : nil
375
+ end
376
+
377
+ # Update a specific glue record for the domain.
378
+ # @see https://api.gandi.net/docs/domains#put-v5-domain-domains-domain-hosts-name
379
+ # @param name [String] the DNS name (excluding FQDN) for the glue record to update (e.g. 'ns1').
380
+ # @param ips [Array<String>] the IPs for the name.
381
+ # @return [String] confirmation message from Gandi.
382
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
383
+ def update_glue_record(name, *ips)
384
+ _response, data = GandiV5.put url('hosts', name), { 'ips' => ips }.to_json
385
+ @glue_records ||= {}
386
+ @glue_records[name] = ips
387
+ data['message']
388
+ end
389
+
390
+ # Delete a specific glue record for the domain.
391
+ # @see https://api.gandi.net/docs/domains#delete-v5-domain-domains-domain-hosts-name
392
+ # @param name [String] the DNS name (excluding FQDN) for the glue record to update (e.g. 'ns1').
393
+ # @return [String] confirmation message from Gandi.
394
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
395
+ def delete_glue_record(name)
396
+ _response, data = GandiV5.delete url('hosts', name)
397
+ @glue_records ||= {}
398
+ @glue_records.delete(name)
399
+ data['message']
400
+ end
401
+
402
+ # @see GandiV5::Email::Mailbox.list
403
+ def mailboxes(**params)
404
+ GandiV5::Email::Mailbox.list(**params, fqdn: fqdn)
405
+ end
406
+
407
+ # @see GandiV5::Email::Slot.list
408
+ def mailbox_slots(**params)
409
+ GandiV5::Email::Slot.list(**params, fqdn: fqdn)
410
+ end
411
+
412
+ # @see GandiV5::Email::Forward.list
413
+ def email_forwards(**params)
414
+ GandiV5::Email::Forward.list(**params, fqdn: fqdn)
415
+ end
416
+
283
417
  # Create (register) a new domain.
284
418
  # Warning! This is not a free operation. Please ensure your prepaid account has enough credit.
285
419
  # @see https://api.gandi.net/docs/domains#post-v5-domain-domains
286
420
  # @param fqdn [String, #to_s] the fully qualified domain name to create.
421
+ # @param dry_run [Boolean]
422
+ # whether the details should be checked instead of actually creating the domain.
423
+ # @param sharing_id [String] either:
424
+ # * nil (default) - nothing special happens
425
+ # * an organization ID - pay using another organization
426
+ # (you need to have billing permissions on the organization
427
+ # and use the same organization name for the domain name's owner).
428
+ # The invoice will be edited using this organization's information.
429
+ # * a reseller ID - buy a domain for a customer using a reseller account
430
+ # (you need to have billing permissions on the reseller organization
431
+ # and have your customer's information for the owner).
432
+ # The invoice will be edited using the reseller organization's information.
287
433
  # @param owner [GandiV5::Domain::Contact, #to_gandi, #to_h] (required)
288
434
  # the owner of the new domain.
289
435
  # @param admin [GandiV5::Domain::Contact, #to_gandi, #to_h] (optional, defaults to owner)
@@ -308,25 +454,24 @@ class GandiV5
308
454
  # @param nameservers [Array<String>, #to_gandi, #to_json] (optional)
309
455
  # List of nameservers. Gandi's LiveDNS nameservers are used if omitted..
310
456
  # @param price [Numeric, #to_gandi, #to_json] (optional) unknown - not documented at Gandi.
311
- # @param reselle_id [String, #to_gandi, #to_json] (optional) unknown - not documented at Gandi.
457
+ # @param resellee_id [String, #to_gandi, #to_json] (optional) unknown - not documented at Gandi.
312
458
  # @param smd [String, #to_gandi, #to_json] (optional)
313
459
  # Contents of a Signed Mark Data file (used for newgtld sunrises, tld_period must be sunrise).
314
460
  # @param tld_period ["sunrise", "landrush", "eap1", "eap2", "eap3", "eap4", "eap5", "eap6",
315
461
  # "eap7", "eap8", "eap9", "golive", #to_gandi, #to_json] (optional)
316
462
  # @see https://docs.gandi.net/en/domain_names/register/new_gtld.html
317
- # @param dry_run [Boolean] whether the details should be checked
318
- # instead of actually creating the domain
319
463
  # @return [GandiV5::Domain] the created domain
320
464
  # @return [Hash] if doing a dry run, you get what Gandi returns
321
465
  # @raise [GandiV5::Error::GandiError] if Gandi returns an error
322
- def self.create(fqdn, dry_run: false, **params)
466
+ def self.create(fqdn, dry_run: false, sharing_id: nil, **params)
323
467
  fail ArgumentError, 'missing keyword: owner' unless params.key?(:owner)
324
468
 
325
469
  body = params.merge(fqdn: fqdn)
326
470
  .transform_values { |val| val.respond_to?(:to_gandi) ? val.to_gandi : val }
327
471
  .to_json
472
+ url_ = sharing_id ? "#{url}?sharing_id=#{sharing_id}" : url
328
473
 
329
- response, data = GandiV5.post(url, body, 'Dry-Run': dry_run ? 1 : 0)
474
+ response, data = GandiV5.post(url_, body, 'Dry-Run': dry_run ? 1 : 0)
330
475
  dry_run ? data : fetch(response.headers[:location].split('/').last)
331
476
  end
332
477
 
@@ -347,7 +492,7 @@ class GandiV5
347
492
  # @param page [#each<Integer, #to_s>] the page(s) of results to retrieve.
348
493
  # If page is not provided keep querying until an empty list is returned.
349
494
  # If page responds to .each then iterate until an empty list is returned.
350
- # @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
495
+ # @param per_page [Integer, #to_s] (optional default 100) how many results to get per page.
351
496
  # @param fqdn [String, #to_s] (optional)
352
497
  # filters the list by domain name, with optional patterns.
353
498
  # e.g. "example.net", "example.*", "*ample.com"
@@ -356,25 +501,19 @@ class GandiV5
356
501
  # @return [Array<GandiV5::Domain>]
357
502
  # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
358
503
  def self.list(page: (1..), per_page: 100, **params)
359
- page = [page.to_i] unless page.respond_to?(:each)
360
-
361
504
  domains = []
362
- page.each do |page_number|
363
- _resp, data = GandiV5.get url, params: params.merge(page: page_number, per_page: per_page)
364
- break if data.empty?
365
-
505
+ GandiV5.paginated_get(url, page, per_page, params: params) do |data|
366
506
  domains += data.map { |domain| from_gandi domain }
367
- break if data.count < per_page
368
507
  end
369
508
  domains
370
509
  end
371
510
 
372
511
  private
373
512
 
374
- def url(extra = nil)
513
+ def url(*extra)
375
514
  "#{BASE}domain/domains/" +
376
515
  CGI.escape(fqdn) +
377
- (extra ? "/#{extra}" : '')
516
+ (extra.empty? ? '' : "/#{extra.join('/')}")
378
517
  end
379
518
 
380
519
  def self.url(fqdn = nil)
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'availability/tax'
4
- require_relative 'availability/product'
5
-
6
3
  class GandiV5
7
4
  class Domain
8
5
  # Information about the availabillity of processes on a domain.
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'product/price'
4
- require_relative 'product/period'
5
-
6
3
  class GandiV5
7
4
  class Domain
8
5
  class Availability
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class Domain
5
+ # LiveDNS information for a domain.
6
+ # @!attribute [r] current
7
+ # @return [:classic, :livedns, :other]
8
+ # type of nameservers currently set. classic corresponds to Gandi's classic nameservers,
9
+ # livedns is for the new, default, Gandi nameservers and other is for custom nameservers.
10
+ # @!attribute [r] name_servers
11
+ # @return [Array<String>] list of current nameservers.
12
+ # @!attribute [r] dnssec_available
13
+ # @return [nil, Boolean] whether DNSSEC may be applied to the domain.
14
+ # @!attribute [r] livednssec_available
15
+ # @return [nil, Boolean] whether DNSSEC with liveDNS may be applied to this domain.
16
+ class LiveDNS
17
+ include GandiV5::Data
18
+
19
+ members :dnssec_available, :livednssec_available
20
+ member :name_servers, gandi_key: 'nameservers'
21
+ member :current, converter: GandiV5::Data::Converter::Symbol
22
+
23
+ # Check if classic DNS is being used.
24
+ # @return [Boolean]
25
+ def classic?
26
+ current == :classic
27
+ end
28
+
29
+ # Check if custom DNS is being used.
30
+ # @return [Boolean]
31
+ def custom?
32
+ current == :custom
33
+ end
34
+
35
+ # Check if LiveDNS is being used.
36
+ # @return [Boolean]
37
+ def livedns?
38
+ current == :livedns
39
+ end
40
+ end
41
+ end
42
+ end
@@ -17,8 +17,6 @@ class GandiV5
17
17
  # @return [Integer]
18
18
  # @!attribute [r] minimum
19
19
  # @return [Integer]
20
- # @!attribute [r] contracts
21
- # @return [Array<GandiV5::Domain::Contract>]
22
20
  class RenewalInformation
23
21
  include GandiV5::Data
24
22
 
@@ -26,7 +24,6 @@ class GandiV5
26
24
 
27
25
  member :begins_at, converter: GandiV5::Data::Converter::Time
28
26
  member :ends_at, converter: GandiV5::Data::Converter::Time
29
- member :contracts, converter: GandiV5::Domain::Contract, array: true
30
27
 
31
28
  # Check if the domain is currently renewable.
32
29
  # @return [Boolean]
@@ -7,14 +7,22 @@ class GandiV5
7
7
  # @return [String]
8
8
  # @!attribute [r] name
9
9
  # @return [String]
10
+ # @!attribute [r] type
11
+ # @return [String]
10
12
  # @!attribute [r] reseller
11
13
  # @return [nil, Boolean]
14
+ # @!attribute [r] reseller_details
15
+ # @return [nil, GandiV5::Domain::SharingSpace]
12
16
  class SharingSpace
13
17
  include GandiV5::Data
14
18
 
15
- members :name, :reseller
19
+ members :name, :type, :reseller
16
20
  member :uuid, gandi_key: 'id'
17
-
21
+ member(
22
+ :reseller_details,
23
+ gandi_key: 'sharing_space',
24
+ converter: GandiV5::Domain::SharingSpace
25
+ )
18
26
  alias sharing_space_uuid uuid
19
27
  end
20
28
  end
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'email/mailbox'
4
- require_relative 'email/offer'
5
- require_relative 'email/slot'
6
-
7
3
  class GandiV5
8
4
  # Gandi Email Mailbox Management API.
9
5
  class Email
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ class GandiV5
4
+ class Email
5
+ # A forwarding address that lives within a domain.
6
+ # @see https://docs.gandi.net/en/gandimail/forwarding_and_aliases/
7
+ # @!attribute [r] source
8
+ # @return [String] the source email address ("alice" rather than "alice@example.com").
9
+ # @!attribute [r] destinations
10
+ # @return [Array<String>] list of destination email addresses.
11
+ # @!attribute [r] fqdn
12
+ # @return [String] domain name.
13
+ class Forward
14
+ include GandiV5::Data
15
+
16
+ members :source, :fqdn
17
+ member :destinations, array: true
18
+
19
+ # Delete the forwarding.
20
+ # @see https://api.gandi.net/docs/email/#delete-v5-email-forwards-domain-source
21
+ # @return [String] The confirmation message from Gandi.
22
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
23
+ def delete
24
+ _response, data = GandiV5.delete url
25
+ data['message']
26
+ end
27
+
28
+ # Update the forwarding.
29
+ # @see https://api.gandi.net/docs/email/#put-v5-email-forwards-domain-source
30
+ # @param destinations [Array<String, #to_s>] new list of destination email addresses.
31
+ # @return [String] The confirmation message from Gandi.
32
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
33
+ def update(*destinations)
34
+ fail ArgumentError, 'destinations can\'t be empty' if destinations.none?
35
+
36
+ _response, data = GandiV5.put url, { destinations: destinations }.to_json
37
+ @destinations = destinations.map(&:to_s)
38
+ data['message']
39
+ end
40
+
41
+ # Returns the string representation of the forwarding.
42
+ # @return [String]
43
+ def to_s
44
+ "#{source}@#{fqdn} -> #{destinations.join(', ')}"
45
+ end
46
+
47
+ # Create a new forward.
48
+ # @see https://api.gandi.net/docs/email/#post-v5-email-forwards-domain
49
+ # @param fqdn [String, #to_s] the fully qualified domain name for the forward.
50
+ # @param source [String, #to_s]
51
+ # the source email address ("alice" rather than "alice@example.com").
52
+ # @param destinations [Array<String, #to_s>] list of destination email addresses.
53
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
54
+ def self.create(fqdn, source, *destinations)
55
+ fail ArgumentError, 'destinations can\'t be empty' if destinations.none?
56
+
57
+ body = {
58
+ source: source,
59
+ destinations: destinations
60
+ }.to_json
61
+ _response, _data = GandiV5.post url(fqdn), body
62
+
63
+ new fqdn: fqdn, source: source, destinations: destinations
64
+ end
65
+
66
+ # List forwards for a domain.
67
+ # @see https://api.gandi.net/docs/email/#get-v5-email-forwards-domain
68
+ # @param fqdn [String, #to_s] the fully qualified domain name for the forwards.
69
+ # @param page [Integer, #each<Integer>] which page(s) of results to get.
70
+ # If page is not provided keep querying until an empty list is returned.
71
+ # If page responds to .each then iterate until an empty list is returned.
72
+ # @param per_page [Integer, #to_s] (optional default 100) how many results ot get per page.
73
+ # @param sort_by [#to_s] (optional default "login")
74
+ # how to sort the results ("login", "-login").
75
+ # @param source [String] (optional) filter the source (pattern)
76
+ # e.g. ("alice" "*lice", "alic*").
77
+ # @return [Array<GandiV5::Email::Forward>]
78
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
79
+ def self.list(fqdn, page: (1..), per_page: 100, **params)
80
+ params.reject! { |_k, v| v.nil? }
81
+
82
+ mailboxes = []
83
+ GandiV5.paginated_get(url(fqdn), page, per_page, params: params) do |data|
84
+ mailboxes += data.map { |mailbox| from_gandi mailbox.merge(fqdn: fqdn) }
85
+ end
86
+ mailboxes
87
+ end
88
+
89
+ private
90
+
91
+ def url
92
+ "#{BASE}email/forwards/#{CGI.escape fqdn}/#{CGI.escape source}"
93
+ end
94
+
95
+ def self.url(fqdn, source = nil)
96
+ "#{BASE}email/forwards/#{CGI.escape fqdn}" +
97
+ (source ? "/#{CGI.escape source}" : '')
98
+ end
99
+ private_class_method :url
100
+ end
101
+ end
102
+ end