gandi_v5 0.1.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +14 -4
  4. data/.travis.yml +16 -1
  5. data/CHANGELOG.md +80 -2
  6. data/FUNDING.yml +10 -0
  7. data/Guardfile +5 -6
  8. data/LICENSE.md +2 -6
  9. data/README.md +17 -23
  10. data/gandi_v5.gemspec +4 -3
  11. data/lib/gandi_v5.rb +54 -15
  12. data/lib/gandi_v5/billing.rb +2 -4
  13. data/lib/gandi_v5/billing/info.rb +0 -2
  14. data/lib/gandi_v5/data.rb +1 -2
  15. data/lib/gandi_v5/data/converter.rb +0 -4
  16. data/lib/gandi_v5/data/converter/integer.rb +26 -0
  17. data/lib/gandi_v5/domain.rb +201 -101
  18. data/lib/gandi_v5/domain/auto_renew.rb +4 -4
  19. data/lib/gandi_v5/domain/availability.rb +46 -0
  20. data/lib/gandi_v5/domain/availability/product.rb +49 -0
  21. data/lib/gandi_v5/domain/availability/product/period.rb +24 -0
  22. data/lib/gandi_v5/domain/availability/product/price.rb +36 -0
  23. data/lib/gandi_v5/domain/availability/tax.rb +20 -0
  24. data/lib/gandi_v5/domain/live_dns.rb +42 -0
  25. data/lib/gandi_v5/domain/renewal_information.rb +0 -3
  26. data/lib/gandi_v5/domain/sharing_space.rb +10 -2
  27. data/lib/gandi_v5/domain/tld.rb +57 -0
  28. data/lib/gandi_v5/email.rb +0 -4
  29. data/lib/gandi_v5/email/forward.rb +108 -0
  30. data/lib/gandi_v5/email/mailbox.rb +85 -24
  31. data/lib/gandi_v5/email/mailbox/responder.rb +43 -2
  32. data/lib/gandi_v5/email/offer.rb +2 -2
  33. data/lib/gandi_v5/email/slot.rb +52 -18
  34. data/lib/gandi_v5/error.rb +0 -2
  35. data/lib/gandi_v5/error/gandi_error.rb +2 -2
  36. data/lib/gandi_v5/live_dns.rb +20 -4
  37. data/lib/gandi_v5/live_dns/domain.rb +21 -150
  38. data/lib/gandi_v5/live_dns/has_zone_records.rb +153 -0
  39. data/lib/gandi_v5/live_dns/record_set.rb +1 -1
  40. data/lib/gandi_v5/live_dns/zone.rb +24 -165
  41. data/lib/gandi_v5/live_dns/zone/snapshot.rb +27 -8
  42. data/lib/gandi_v5/organization.rb +39 -6
  43. data/lib/gandi_v5/organization/customer.rb +90 -0
  44. data/lib/gandi_v5/version.rb +1 -1
  45. data/spec/.rubocop.yml +9 -2
  46. data/spec/features/domain_spec.rb +2 -2
  47. data/spec/features/livedns_zone_spec.rb +12 -13
  48. data/spec/fixtures/bodies/GandiV5_Billing/{info.yaml → info.yml} +0 -0
  49. data/spec/fixtures/bodies/GandiV5_Domain/{get.yaml → fetch.yml} +8 -0
  50. data/spec/fixtures/bodies/GandiV5_Domain/{fetch_contacts.yaml → fetch_contacts.yml} +0 -0
  51. data/spec/fixtures/bodies/GandiV5_Domain/fetch_glue_records.yml +7 -0
  52. data/spec/fixtures/bodies/GandiV5_Domain/fetch_livedns.yml +6 -0
  53. data/spec/fixtures/bodies/GandiV5_Domain/fetch_name_servers.yml +2 -0
  54. data/spec/fixtures/bodies/GandiV5_Domain/{renewal_info.yaml → fetch_renewal_info.yml} +0 -3
  55. data/spec/fixtures/bodies/GandiV5_Domain/{restore_info.yaml → fetch_restore_info.yml} +0 -0
  56. data/spec/fixtures/bodies/GandiV5_Domain/{list.yaml → list.yml} +1 -0
  57. data/spec/fixtures/bodies/{GandiV5_Domain/availability.yaml → GandiV5_Domain_Availability/fetch.yml} +0 -0
  58. data/spec/fixtures/bodies/{GandiV5_Domain/tld.yaml → GandiV5_Domain_TLD/fetch.yml} +0 -0
  59. data/spec/fixtures/bodies/{GandiV5_Domain/tlds.yaml → GandiV5_Domain_TLD/list.yml} +0 -0
  60. data/spec/fixtures/bodies/GandiV5_Email_Forward/list.yml +6 -0
  61. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{get.yaml → fetch.yml} +0 -0
  62. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{list.yaml → list.yml} +0 -0
  63. data/spec/fixtures/bodies/GandiV5_Email_Slot/{get.yaml → fetch.yml} +0 -0
  64. data/spec/fixtures/bodies/GandiV5_Email_Slot/{list.yaml → list.yml} +0 -0
  65. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{get.yaml → fetch.yml} +0 -0
  66. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{list.yaml → list.yml} +0 -0
  67. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{get.yaml → fetch.yml} +0 -0
  68. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{list.yaml → list.yml} +0 -0
  69. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/{get.yaml → fetch.yml} +0 -0
  70. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/list.yml +3 -0
  71. data/spec/fixtures/bodies/GandiV5_Organization/{get.yaml → fetch.yml} +0 -0
  72. data/spec/fixtures/bodies/GandiV5_Organization/list.yml +7 -0
  73. data/spec/fixtures/bodies/GandiV5_Organization_Customer/list.yml +8 -0
  74. data/spec/fixtures/vcr/Domain_features/List_domains.yml +2 -1
  75. data/spec/spec_helper.rb +2 -2
  76. data/spec/units/gandi_v5/billing_spec.rb +4 -4
  77. data/spec/units/gandi_v5/data/converter/integer_spec.rb +16 -0
  78. data/spec/units/gandi_v5/domain/auto_renew_spec.rb +5 -5
  79. data/spec/units/gandi_v5/domain/availability/product/period_spec.rb +4 -0
  80. data/spec/units/gandi_v5/domain/availability/product/price_spec.rb +4 -0
  81. data/spec/units/gandi_v5/domain/availability/product_spec.rb +4 -0
  82. data/spec/units/gandi_v5/domain/availability/tax_spec.rb +4 -0
  83. data/spec/units/gandi_v5/domain/availability_spec.rb +43 -0
  84. data/spec/units/gandi_v5/domain/live_dns_spec.rb +45 -0
  85. data/spec/units/gandi_v5/domain/tld_spec.rb +29 -0
  86. data/spec/units/gandi_v5/domain_spec.rb +359 -91
  87. data/spec/units/gandi_v5/email/forward_spec.rb +121 -0
  88. data/spec/units/gandi_v5/email/mailbox/responder_spec.rb +52 -0
  89. data/spec/units/gandi_v5/email/mailbox_spec.rb +174 -33
  90. data/spec/units/gandi_v5/email/offer_spec.rb +1 -1
  91. data/spec/units/gandi_v5/email/slot_spec.rb +113 -17
  92. data/spec/units/gandi_v5/live_dns/domain_spec.rb +73 -43
  93. data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +32 -3
  94. data/spec/units/gandi_v5/live_dns/zone_spec.rb +70 -52
  95. data/spec/units/gandi_v5/live_dns_spec.rb +24 -0
  96. data/spec/units/gandi_v5/organization/customer_spec.rb +81 -0
  97. data/spec/units/gandi_v5/organization_spec.rb +52 -1
  98. data/spec/units/gandi_v5_spec.rb +56 -19
  99. metadata +71 -29
  100. data/TODO.md +0 -29
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'mailbox/responder'
4
-
5
3
  class GandiV5
6
4
  class Email
7
5
  # A mailbox that lives within a domain.
@@ -44,33 +42,43 @@ class GandiV5
44
42
 
45
43
  alias mailbox_uuid uuid
46
44
 
45
+ # Create a new GandiV5::Email::Mailbox
46
+ # @param members [Hash<Symbol => Object>]
47
+ # @return [GandiV5::Email::Slot]
48
+ def initialize(**members)
49
+ super(**members)
50
+ responder.instance_exec(self) { |mb| @mailbox = mb } if responder?
51
+ end
52
+
47
53
  # Delete the mailbox and it's contents.
48
54
  # If you delete a mailbox for which you have purchased a slot,
49
55
  # this action frees the slot so it once again becomes available
50
56
  # for use with a new mailbox, or for deletion.
51
57
  # @see https://api.gandi.net/docs/email#delete-v5-email-mailboxes-domain-mailbox_id
52
58
  # @return [String] The confirmation message from Gandi.
53
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
59
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
54
60
  def delete
55
- data = GandiV5.delete url
61
+ _response, data = GandiV5.delete url
56
62
  data['message']
57
63
  end
58
64
 
59
65
  # Purge the contents of the mailbox.
60
66
  # @see https://api.gandi.net/docs/email#delete-v5-email-mailboxes-domain-mailbox_id-contents
61
67
  # @return [String] The confirmation message from Gandi.
62
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
68
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
63
69
  def purge
64
- data = GandiV5.delete "#{url}/contents"
70
+ _response, data = GandiV5.delete "#{url}/contents"
65
71
  data['message']
66
72
  end
67
73
 
68
74
  # Requery Gandi fo this mailbox's information.
69
75
  # @return [GandiV5::Email::Mailbox]
70
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
76
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
71
77
  def refresh
72
- data = GandiV5.get url
78
+ _response, data = GandiV5.get url
73
79
  from_gandi data
80
+ responder.instance_exec(self) { |mb| @mailbox = mb } if responder?
81
+ self
74
82
  end
75
83
 
76
84
  # Update the mailbox's settings.
@@ -81,8 +89,7 @@ class GandiV5
81
89
  # @param responder [Hash, GandiV5::Mailbox::Responder, #to_gandi, #to_h]
82
90
  # auto responder settings.
83
91
  # @return [String] The confirmation message from Gandi.
84
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
85
- # rubocop:disable Metrics/AbcSize
92
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
86
93
  def update(**body)
87
94
  return 'Nothing to update.' if body.empty?
88
95
 
@@ -93,11 +100,43 @@ class GandiV5
93
100
  body[:responder] = responder.respond_to?(:to_gandi) ? responder.to_gandi : responder.to_h
94
101
  end
95
102
 
96
- data = GandiV5.patch url, body.to_json
103
+ _response, data = GandiV5.patch url, body.to_json
97
104
  refresh
98
105
  data['message']
99
106
  end
100
- # rubocop:enable Metrics/AbcSize
107
+
108
+ # Upgrade a standard mailbox to premium.
109
+ # If the current slot is a free one, a new premium slot is created and
110
+ # used for the mailbox. Otherwise, the slot is upgraded to premium.
111
+ # @see https://api.gandi.net/docs/email#patch-v5-email-mailboxes-domain-mailbox_id-type
112
+ # @param sharing_id [String, #to_s, nil] (optional)
113
+ # the organisation ID to bill for the mailbox.
114
+ # @param dry_run [Boolean] whether the details should be checked instead
115
+ # of actually upgrading the mailbox.
116
+ # @return [true] if the mailbox was upgraded
117
+ # @return [false] if the mailbox was not upgraded (it's already premium)
118
+ # @return [Hash] if doing a dry run, you get what Gandi returns
119
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error
120
+ def upgrade(sharing_id: nil, dry_run: false)
121
+ patch_type :premium, sharing_id, dry_run
122
+ end
123
+
124
+ # Downgrade a premium mailbox to standard.
125
+ # If a free slot is available, the premium slot is destroyed
126
+ # (and refunded) and the free one is used for the mailbox.
127
+ # Otherwise, the slot is downgraded to standard.
128
+ # @see https://api.gandi.net/docs/email#patch-v5-email-mailboxes-domain-mailbox_id-type
129
+ # @param sharing_id [String, #to_s, nil] (optional)
130
+ # the organisation ID to bill for the mailbox.
131
+ # @param dry_run [Boolean] whether the details should be checked instead
132
+ # of actually downgrading the mailbox.
133
+ # @return [true] if the mailbox was downgraded
134
+ # @return [false] if the mailbox was not downgraded (it's already standard)
135
+ # @return [Hash] if doing a dry run, you get what Gandi returns
136
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error
137
+ def downgrade(sharing_id: nil, dry_run: false)
138
+ patch_type :standard, sharing_id, dry_run
139
+ end
101
140
 
102
141
  # Create a new mailbox.
103
142
  # Note that before you can create a mailbox, you must have a slot available.
@@ -107,13 +146,19 @@ class GandiV5
107
146
  # @param password [String, #to_s] the password to use.
108
147
  # @param aliases [Array<String, #to_s>] any alternative email address to be used.
109
148
  # @param type [:standard, :premium] the type of mailbox slot to use.
110
- # @return [String] The confirmation message from Gandi.
111
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
112
- # TODO: Fetch created mailbox
113
- def self.create(fqdn, login, password, aliases: [], type: :standard)
114
- # TODO: Check type is valid
149
+ # @param dry_run [Boolean] whether the details should be checked instead
150
+ # of actually creating the mailbox.
151
+ # @return [GandiV5::Email::Mailbox] The created mailbox.
152
+ # @raise [GandiV5::Error] if no slots are available.
153
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
154
+ # rubocop:disable Metrics/AbcSize
155
+ def self.create(fqdn, login, password, aliases: [], type: :standard, dry_run: false)
156
+ fail ArgumentError, "#{type.inspect} is not a valid type" unless TYPES.include?(type)
157
+ if GandiV5::Email::Slot.list.none? { |slot| slot.mailbox_type == type && slot.inactive? }
158
+ fail GandiV5::Error, "no available #{type} slots"
159
+ end
160
+
115
161
  check_password password
116
- # TODO: Check if a slot is available
117
162
 
118
163
  body = {
119
164
  mailbox_type: type,
@@ -122,18 +167,20 @@ class GandiV5
122
167
  aliases: aliases.push
123
168
  }.to_json
124
169
 
125
- data = GandiV5.post url(fqdn), body
126
- data['message']
170
+ response, data = GandiV5.post(url(fqdn), body, 'Dry-Run': dry_run ? 1 : 0)
171
+
172
+ dry_run ? data : fetch(fqdn, response.headers[:location].split('/').last)
127
173
  end
174
+ # rubocop:enable Metrics/AbcSize
128
175
 
129
176
  # Get information for a mailbox.
130
177
  # @see https://api.gandi.net/docs/email#get-v5-email-mailboxes-domain-mailbox_id
131
178
  # @param fqdn [String, #to_s] the fully qualified domain name for the mailbox.
132
179
  # @param uuid [String, #to_s] unique identifier of the mailbox.
133
180
  # @return [GandiV5::Email::Mailbox]
134
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
181
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
135
182
  def self.fetch(fqdn, uuid)
136
- data = GandiV5.get url(fqdn, uuid)
183
+ _response, data = GandiV5.get url(fqdn, uuid)
137
184
  from_gandi data
138
185
  end
139
186
 
@@ -149,7 +196,7 @@ class GandiV5
149
196
  # @param login [String] (optional) filter the list by login (pattern)
150
197
  # e.g. ("alice" "*lice", "alic*").
151
198
  # @return [Array<GandiV5::Email::Mailbox>]
152
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
199
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
153
200
  def self.list(fqdn, page: (1..), **params)
154
201
  page = [page.to_i] unless page.respond_to?(:each)
155
202
 
@@ -158,7 +205,7 @@ class GandiV5
158
205
 
159
206
  mailboxes = []
160
207
  page.each do |page_number|
161
- data = GandiV5.get url(fqdn), params: params.merge(page: page_number)
208
+ _response, data = GandiV5.get url(fqdn), params: params.merge(page: page_number)
162
209
  break if data.empty?
163
210
 
164
211
  mailboxes += data.map { |mailbox| from_gandi mailbox }
@@ -231,6 +278,20 @@ class GandiV5
231
278
  def crypt_password(password)
232
279
  self.class.send :crypt_password, password
233
280
  end
281
+
282
+ def patch_type(new_type, sharing_id, dry_run)
283
+ fail ArgumentError unless TYPES.include?(new_type)
284
+ return false if type == new_type
285
+
286
+ url_ = "#{url}/type"
287
+ url_ = sharing_id ? "#{url_}?sharing_id=#{sharing_id}" : url_
288
+ body = { mailbox_type: new_type }
289
+
290
+ _response, data = GandiV5.patch(url_, body.to_json, 'Dry-Run': dry_run ? 1 : 0)
291
+
292
+ @type = new_type unless dry_run
293
+ dry_run ? data : true
294
+ end
234
295
  end
235
296
  end
236
297
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # TODO: Allow enable/disable from here too ???
4
-
5
3
  class GandiV5
6
4
  class Email
7
5
  class Mailbox
@@ -15,13 +13,26 @@ class GandiV5
15
13
  # @return [nil, Time]
16
14
  # @!attribute [r] message
17
15
  # @return [nil, String]
16
+ # @!attribute [r] mailbox
17
+ # @return [GandiV5::Email::Mailbox] the mailbox this repsonder belongs to.
18
18
  class Responder
19
19
  include GandiV5::Data
20
20
 
21
+ attr_reader :mailbox
22
+
21
23
  members :enabled, :message
22
24
  member :starts_at, converter: GandiV5::Data::Converter::Time
23
25
  member :ends_at, converter: GandiV5::Data::Converter::Time
24
26
 
27
+ # Create a new GandiV5::Email::Mailbox::Responder
28
+ # @param mailbox [GandiV5::Email::Mailbox] the mailbox this responder belongs to.
29
+ # @param members [Hash<Symbol => Object>]
30
+ # @return [GandiV5::Email::Slot]
31
+ def initialize(mailbox: nil, **members)
32
+ super(**members)
33
+ @mailbox = mailbox
34
+ end
35
+
25
36
  # Check if this responder is currently active.
26
37
  # @return [Boolean] whether the responder is enabled,
27
38
  # started in the past and ends in the future.
@@ -30,6 +41,36 @@ class GandiV5
30
41
  (starts_at.nil? || starts_at < Time.now) &&
31
42
  (ends_at.nil? || ends_at > Time.now)
32
43
  end
44
+
45
+ # Enable the auto responder in Gandi.
46
+ # @param message [String]
47
+ # @param starts_at [Time]
48
+ # @param ends_at [Time]
49
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
50
+ def enable(message:, ends_at:, starts_at: Time.now)
51
+ mailbox.update responder: {
52
+ message: message,
53
+ starts_at: GandiV5::Data::Converter::Time.to_gandi(starts_at),
54
+ ends_at: GandiV5::Data::Converter::Time.to_gandi(ends_at),
55
+ enabled: true
56
+ }
57
+
58
+ self.starts_at = starts_at
59
+ self.ends_at = ends_at
60
+ self.message = message
61
+ self.enabled = true
62
+ end
63
+
64
+ # Disable the auto responder in Gandi.
65
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
66
+ def disable
67
+ mailbox.update responder: { enabled: false }
68
+
69
+ self.starts_at = nil
70
+ self.ends_at = nil
71
+ self.message = nil
72
+ self.enabled = false
73
+ end
33
74
  end
34
75
  end
35
76
  end
@@ -17,9 +17,9 @@ class GandiV5
17
17
  # @see https://api.gandi.net/docs/email#get-v5-email-offers-domain
18
18
  # @param fqdn [String, #to_s] the fully qualified domain name to get the offer for.
19
19
  # @return [GandiV5::Email::Offer]
20
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
20
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
21
21
  def self.fetch(fqdn)
22
- data = GandiV5.get "#{BASE}email/offers/#{CGI.escape fqdn}"
22
+ _response, data = GandiV5.get "#{BASE}email/offers/#{CGI.escape fqdn}"
23
23
  from_gandi data
24
24
  end
25
25
  end
@@ -39,12 +39,12 @@ class GandiV5
39
39
  alias slot_id id
40
40
 
41
41
  # Create a new GandiV5::Email::Slot
42
- # @param string [fqdn] the fully qualified domain this slot belongs to.
42
+ # @param fqdn [String] the fully qualified domain this slot belongs to.
43
43
  # @param members [Hash<Symbol => Object>]
44
44
  # @return [GandiV5::Email::Slot]
45
45
  def initialize(fqdn: nil, **members)
46
46
  super(**members)
47
- @fqdn = fqdn if fqdn
47
+ @fqdn = fqdn
48
48
  end
49
49
 
50
50
  # Delete this slot if it is inactive and refundable.
@@ -53,20 +53,23 @@ class GandiV5
53
53
  # @see GandiV5::Email::Mailbox#delete
54
54
  # @see https://api.gandi.net/docs/email#delete-v5-email-slots-domain-slot_id
55
55
  # @return [String] The confirmation message from Gandi.
56
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
57
- # TODO: check for inactiveness
58
- # TODO: check for refundableness
56
+ # @raise [GandiV5::Error] if slot is active.
57
+ # @raise [GandiV5::Error] if slot is not refundable.
58
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
59
59
  def delete
60
- data = GandiV5.delete url
60
+ fail GandiV5::Error, 'slot can\'t be deleted whilst active' if active?
61
+ fail GandiV5::Error, 'slot can\'t be deleted if it\'s not refundable' unless refundable
62
+
63
+ _response, data = GandiV5.delete url
61
64
  data['message']
62
65
  end
63
66
 
64
67
  # Requery Gandi for this slot's information.
65
68
  # @see https://api.gandi.net/docs/email#get-v5-email-slots-domain-slot_id
66
69
  # @return [GandiV5::Email::Slot]
67
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
70
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
68
71
  def refresh
69
- data = GandiV5.get url
72
+ _response, data = GandiV5.get url
70
73
  from_gandi data
71
74
  end
72
75
 
@@ -75,17 +78,24 @@ class GandiV5
75
78
  # but require more mailboxes on that domain, you must first purchase additional slots.
76
79
  # @see https://api.gandi.net/docs/email#post-v5-email-slots-domain
77
80
  # @param fqdn [String, #to_s] the fully qualified domain name to add the slot to.
78
- # @param type [:standard, :premium] Tyhe type of slot to add.
81
+ # @param type [:standard, :premium] The type of slot to add.
82
+ # @param sharing_id [nil, String, #to_s] either:
83
+ # * nil (default) - nothing special happens
84
+ # * an organization ID - pay using another organization
85
+ # (you need to have billing permissions on the organization
86
+ # and use the same organization name for the domain name's owner).
87
+ # The invoice will be edited using this organization's information.
79
88
  # @return [String] The confirmation message from Gandi.
80
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
81
- # TODO: Fetch created slot
82
- def self.create(fqdn, type = :standard)
89
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
90
+ def self.create(fqdn, type: :standard, sharing_id: nil)
83
91
  body = {
84
92
  mailbox_type: type
85
93
  }.to_json
86
94
 
87
- data = GandiV5.post url(fqdn), body
88
- data['message']
95
+ url_ = url(fqdn)
96
+ url_ += "?sharing_id=#{sharing_id}" if sharing_id
97
+ response, _data = GandiV5.post url_, body
98
+ fetch fqdn, response.headers[:location].split('/').last
89
99
  end
90
100
 
91
101
  # Get information for a slot.
@@ -93,9 +103,9 @@ class GandiV5
93
103
  # @param fqdn [String, #to_s] the fully qualified domain name the slot is on.
94
104
  # @param id [String, #to_s] the ID of the slot to fetch.
95
105
  # @return [GandiV5::Email::Slot]
96
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
106
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
97
107
  def self.fetch(fqdn, id)
98
- data = GandiV5.get url(fqdn, id)
108
+ _response, data = GandiV5.get url(fqdn, id)
99
109
  slot = from_gandi data
100
110
  slot.instance_eval { @fqdn = fqdn }
101
111
  slot
@@ -105,9 +115,9 @@ class GandiV5
105
115
  # @see https://api.gandi.net/docs/email#
106
116
  # @param fqdn [String, #to_s] the fully qualified domain name to list slots for.
107
117
  # @return [Array<GandiV5::Email::Slot>]
108
- # @raise [GandiV5::Error::GandiError::GandiError] if Gandi returns an error.
118
+ # @raise [GandiV5::Error::GandiError] if Gandi returns an error.
109
119
  def self.list(fqdn)
110
- data = GandiV5.get url(fqdn)
120
+ _response, data = GandiV5.get url(fqdn)
111
121
  data.map { |item| from_gandi item }
112
122
  .each { |item| item.instance_eval { @fqdn = fqdn } }
113
123
  end
@@ -118,6 +128,30 @@ class GandiV5
118
128
  status.eql?(:active)
119
129
  end
120
130
 
131
+ # Check if the slot is inactive (not in use)
132
+ # @return [Boolean]
133
+ def inactive?
134
+ status.eql?(:inactive)
135
+ end
136
+
137
+ # Check if the slot's mailbox_type is :free
138
+ # @return [Boolean]
139
+ def free?
140
+ mailbox_type.eql?(:free)
141
+ end
142
+
143
+ # Check if the slot's mailbox_type is :standard
144
+ # @return [Boolean]
145
+ def standard?
146
+ mailbox_type.eql?(:standard)
147
+ end
148
+
149
+ # Check if the slot's mailbox_type is :premium
150
+ # @return [Boolean]
151
+ def premium?
152
+ mailbox_type.eql?(:premium)
153
+ end
154
+
121
155
  private
122
156
 
123
157
  def url
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'error/gandi_error'
4
-
5
3
  class GandiV5
6
4
  # Generic error class for errors occuring using the API.
7
5
  class Error < RuntimeError
@@ -4,9 +4,9 @@ class GandiV5
4
4
  class Error < RuntimeError
5
5
  # Generic error class for errors returned by Gandi.
6
6
  class GandiError < GandiV5::Error
7
- # Generate a new GandiV5::Error::GandiError::GandiError from the hash returned by Gandi.
7
+ # Generate a new GandiV5::Error::GandiError from the hash returned by Gandi.
8
8
  # @param hash [Hash] the hash returned by Gandi.
9
- # @return [GandiV5::Error::GandiError::GandiError]
9
+ # @return [GandiV5::Error::GandiError]
10
10
  def self.from_hash(hash)
11
11
  hash['errors'] ||= []
12
12
 
@@ -11,6 +11,26 @@ class GandiV5
11
11
  WKS SRV LOC SPF CAA DS SSHFP PTR KEY DNAME TLSA OPENPGPKEY CDS
12
12
  ].freeze
13
13
 
14
+ # @see GandiV5::LiveDNS::Domain.fetch
15
+ def self.domain(fqdn)
16
+ GandiV5::LiveDNS::Domain.fetch(fqdn)
17
+ end
18
+
19
+ # @see GandiV5::LiveDNS::Domain.list
20
+ def self.domains
21
+ GandiV5::LiveDNS::Domain.list
22
+ end
23
+
24
+ # @see GandiV5::LiveDNS::Zone.fetch
25
+ def self.zone(uuid)
26
+ GandiV5::LiveDNS::Zone.fetch(uuid)
27
+ end
28
+
29
+ # @see GandiV5::LiveDNS::Zone.list
30
+ def self.zones
31
+ GandiV5::LiveDNS::Zone.list
32
+ end
33
+
14
34
  # Raise an error if passed type is invalid.
15
35
  # @param type [String] the record type to check.
16
36
  # @return [nil]
@@ -24,7 +44,3 @@ class GandiV5
24
44
  # rubocop:enable Style/GuardClause
25
45
  end
26
46
  end
27
-
28
- require_relative 'live_dns/record_set'
29
- require_relative 'live_dns/domain'
30
- require_relative 'live_dns/zone'