geocerts 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.document +5 -0
  2. data/.gitignore +6 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +71 -0
  5. data/Rakefile +70 -0
  6. data/VERSION +1 -0
  7. data/autotest/discover.rb +39 -0
  8. data/geocerts.gemspec +144 -0
  9. data/lib/geo_certs.rb +57 -0
  10. data/lib/geo_certs/agreement.rb +18 -0
  11. data/lib/geo_certs/api.rb +29 -0
  12. data/lib/geo_certs/api_object.rb +111 -0
  13. data/lib/geo_certs/certificate.rb +88 -0
  14. data/lib/geo_certs/collection.rb +12 -0
  15. data/lib/geo_certs/csr.rb +31 -0
  16. data/lib/geo_certs/email.rb +8 -0
  17. data/lib/geo_certs/endpoints/agreements.rb +23 -0
  18. data/lib/geo_certs/endpoints/certificates.rb +73 -0
  19. data/lib/geo_certs/endpoints/events.rb +56 -0
  20. data/lib/geo_certs/endpoints/orders.rb +181 -0
  21. data/lib/geo_certs/endpoints/products.rb +30 -0
  22. data/lib/geo_certs/errors.rb +30 -0
  23. data/lib/geo_certs/event.rb +67 -0
  24. data/lib/geo_certs/exceptions.rb +124 -0
  25. data/lib/geo_certs/hash_extension.rb +50 -0
  26. data/lib/geo_certs/order.rb +369 -0
  27. data/lib/geo_certs/order/administrator.rb +23 -0
  28. data/lib/geo_certs/order/contact.rb +30 -0
  29. data/lib/geo_certs/order/extended_validation_approver.rb +23 -0
  30. data/lib/geo_certs/order/organization.rb +39 -0
  31. data/lib/geo_certs/order/renewal_information.rb +31 -0
  32. data/lib/geo_certs/parsers/order_parser.rb +8 -0
  33. data/lib/geo_certs/product.rb +67 -0
  34. data/test/config/initializers/_remote_tests.rb +15 -0
  35. data/test/config/initializers/fakeweb.rb +2 -0
  36. data/test/config/initializers/geocerts.rb +13 -0
  37. data/test/config/initializers/responses.rb +3 -0
  38. data/test/config/test_credentials.example.yml +2 -0
  39. data/test/factories.rb +15 -0
  40. data/test/fixtures/responses.rb +80 -0
  41. data/test/fixtures/responses/agreement.rb +136 -0
  42. data/test/fixtures/responses/certificate.rb +227 -0
  43. data/test/fixtures/responses/event.rb +60 -0
  44. data/test/fixtures/responses/order.rb +272 -0
  45. data/test/fixtures/responses/product.rb +77 -0
  46. data/test/integrations/agreement_test.rb +40 -0
  47. data/test/integrations/api_test.rb +33 -0
  48. data/test/integrations/certificate_test.rb +195 -0
  49. data/test/integrations/event_test.rb +167 -0
  50. data/test/integrations/order_test.rb +510 -0
  51. data/test/integrations/product_test.rb +72 -0
  52. data/test/test_helper.rb +68 -0
  53. data/test/units/certificate_test.rb +21 -0
  54. data/test/units/collection_test.rb +27 -0
  55. data/test/units/csr_test.rb +27 -0
  56. data/test/units/geo_certs_test.rb +19 -0
  57. data/test/units/order/administrator_test.rb +24 -0
  58. data/test/units/order/extended_validation_approver_test.rb +24 -0
  59. data/test/units/order/organization_test.rb +0 -0
  60. data/test/units/order/renewal_information_test.rb +36 -0
  61. data/test/units/order_test.rb +59 -0
  62. data/test/units/product_test.rb +21 -0
  63. metadata +220 -0
@@ -0,0 +1,30 @@
1
+ module GeoCerts
2
+ module Endpoints # :nodoc:
3
+
4
+ module Products # :nodoc:
5
+
6
+ def self.included(base)
7
+ base.class_eval do
8
+ endpoint GeoCerts::API::ENDPOINT do
9
+
10
+ action :products, :url => '/products.xml' do
11
+ parser Parsers::OrderParser do
12
+ element :products do
13
+ elements :product do
14
+ element :name
15
+ element :sku
16
+ element :code
17
+ element 'max-years', :as => :max_years, :type => Integer
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ module GeoCerts
2
+
3
+ class MessageWithCode # :nodoc:
4
+ attr_accessor :code, :message
5
+
6
+ def initialize(attributes = {})
7
+ self.code = attributes[:code].to_i
8
+ self.message = attributes[:message]
9
+ end
10
+
11
+ def to_s #:nodoc:
12
+ "#{self.class.name} ##{code}: #{message}"
13
+ end
14
+ end
15
+
16
+ ##
17
+ # Errors are returned when a request to GeoCerts fails. The exception will be returned
18
+ # with a collection of Error objects which detail the error +code+ and +message+.
19
+ #
20
+ class Error < MessageWithCode
21
+ end
22
+
23
+ ##
24
+ # Warnings may be returned with either successful or unsuccessful requests to GeoCerts.
25
+ # Warnings contain the warning +code+ and +message+.
26
+ #
27
+ class Warning < MessageWithCode
28
+ end
29
+
30
+ end
@@ -0,0 +1,67 @@
1
+ module GeoCerts
2
+
3
+ ##
4
+ # GeoCerts tracks events which occur that are related to your Order(s). This class
5
+ # interfaces with those events to provide collections of all of your events or events
6
+ # against a particular GeoCerts::Order.
7
+ #
8
+ class Event < ApiObject
9
+
10
+ attr_accessor :id,
11
+ :order_id,
12
+ :name,
13
+ :created_at
14
+
15
+
16
+ ##
17
+ # Returns all events which occurred within the requested time window. The server
18
+ # defaults to a 15 minute window.
19
+ #
20
+ # == Options
21
+ #
22
+ # :start_at:: The starting DateTime for the date range
23
+ # :end_at:: The ending DateTime for the date range
24
+ #
25
+ def self.all(options = {})
26
+ prep_date_ranges!(options)
27
+ response = call_api { GeoCerts.api.events(options) }
28
+ build_collection(response) { |response| response[:events][:event] }
29
+ end
30
+
31
+ ##
32
+ # Returns all events which occurred within the requested time window for the requested
33
+ # GeoCerts::Order. The server defaults to a 15 minute window.
34
+ #
35
+ # == Options
36
+ #
37
+ # :start_at:: The starting DateTime for the date range
38
+ # :end_at:: The ending DateTime for the date range
39
+ #
40
+ # === Exceptions
41
+ #
42
+ # This method will raise GeoCerts exceptions if the requested +order_id+ cannot be found.
43
+ #
44
+ def self.find(order_id, options = {})
45
+ prep_date_ranges!(options)
46
+ order_id = order_id.id if order_id.kind_of?(GeoCerts::Order)
47
+ options[:order_id] = order_id
48
+ build_collection(call_api { GeoCerts.api.order_events(options) }) { |response|
49
+ response[:events][:event]
50
+ }
51
+ end
52
+
53
+ ##
54
+ # This method will not raise an exception for a missing +order_id+ in the GeoCerts system.
55
+ # Instead, it will return an empty collection.
56
+ #
57
+ # See GeoCerts::Event.find for more information.
58
+ #
59
+ def self.find_by_order_id(order_id, options = {})
60
+ find(order_id, options)
61
+ rescue GeoCerts::AllowableExceptionWithResponse
62
+ []
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,124 @@
1
+ require 'zlib'
2
+ require 'geo_certs/errors'
3
+
4
+ module GeoCerts
5
+
6
+ HTTP_ERRORS = [ Timeout::Error,
7
+ Errno::EINVAL,
8
+ Errno::ECONNRESET,
9
+ Errno::ECONNREFUSED,
10
+ EOFError,
11
+ Net::HTTPBadResponse,
12
+ Net::HTTPHeaderSyntaxError,
13
+ Net::ProtocolError ]
14
+
15
+ ##
16
+ # The lowest-level GeoCerts exception. All exceptions raised from within this library
17
+ # should be inherited from this exception.
18
+ #
19
+ class Exception < RuntimeError
20
+
21
+ ##
22
+ # Wraps the given exception, keeping the message and backtrace.
23
+ #
24
+ def self.from(exception)
25
+ new("%s: %s" % [exception.class.name, exception.message]).tap do |me|
26
+ me.set_backtrace(exception.backtrace)
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ ##
33
+ # An exception that is raised which contains an HTTP response, and additionally, errors
34
+ # and warnings received from GeoCerts.
35
+ #
36
+ class ExceptionWithResponse < Exception
37
+
38
+ attr_reader :response
39
+
40
+ def initialize(response = nil)
41
+ if response.respond_to?(:response)
42
+ self.response = response.response
43
+ elsif response
44
+ self.response = response
45
+ end
46
+
47
+ self.set_backtrace(response.backtrace) if response.respond_to?(:backtrace)
48
+ end
49
+
50
+ def http_code
51
+ response && response.respond_to?(:code) ? response.code.to_i : nil
52
+ end
53
+
54
+ def errors
55
+ @errors ||= []
56
+ end
57
+
58
+ def warnings
59
+ @warnings ||= []
60
+ end
61
+
62
+ def response=(response) # :nodoc:
63
+ @response = response
64
+
65
+ if !response.respond_to?(:body)
66
+ return @response
67
+ elsif Hash.respond_to?(:from_xml)
68
+ build_objects_for(Hash.from_xml(decode(response['content-encoding'], response.body)))
69
+ else
70
+ build_objects_for(parse_errors(decode(response['content-encoding'], response.body)))
71
+ end
72
+
73
+ @response
74
+ end
75
+
76
+ def to_s # :nodoc:
77
+ "HTTP #{http_code}: A #{self.class.name} exception has occurred"
78
+ end
79
+
80
+ private
81
+
82
+
83
+ def parse_errors(input)
84
+ require 'geo_certs/hash_extension'
85
+ Hash.from_libxml(input)
86
+ end
87
+
88
+ def build_objects_for(errors_and_warnings)
89
+ [errors_and_warnings['errors']['error']].compact.flatten.each do |error|
90
+ self.errors << GeoCerts::Error.new(:code => error['code'], :message => error['message'])
91
+ end
92
+ [errors_and_warnings['errors']['warning']].compact.flatten.each do |error|
93
+ self.warnings << GeoCerts::Warning.new(:code => error['code'], :message => error['message'])
94
+ end
95
+ end
96
+
97
+ def decode(content_encoding, body)
98
+ if content_encoding == 'gzip' and not body.empty?
99
+ Zlib::GzipReader.new(StringIO.new(body)).read
100
+ elsif content_encoding == 'deflate'
101
+ Zlib::Inflate.new.inflate(body)
102
+ else
103
+ body
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ # :stopdoc:
110
+
111
+ class AllowableExceptionWithResponse < ExceptionWithResponse; end
112
+ class Unauthorized < ExceptionWithResponse; end
113
+ class BadRequest < ExceptionWithResponse; end
114
+ class UnprocessableEntity < AllowableExceptionWithResponse; end
115
+ class ResourceNotFound < AllowableExceptionWithResponse; end
116
+ class ResourceNotCreated < Exception; end
117
+ class ResourceInvalid < Exception; end
118
+ class RequestFailed < AllowableExceptionWithResponse; end
119
+ class RequestTimeout < Exception; end
120
+ class ConnectionError < Exception; end
121
+
122
+ # :startdoc:
123
+
124
+ end
@@ -0,0 +1,50 @@
1
+ require 'libxml'
2
+
3
+ class Hash # :nodoc:
4
+ class << self
5
+ def from_libxml(xml, strict=true)
6
+ begin
7
+ LibXML::XML.default_load_external_dtd = false
8
+ LibXML::XML.default_pedantic_parser = strict
9
+ result = LibXML::XML::Parser.string(xml).parse
10
+ return { result.root.name.to_s => xml_node_to_hash(result.root)}
11
+ rescue
12
+ raise $!
13
+ # raise your custom exception here
14
+ end
15
+ end
16
+
17
+ def xml_node_to_hash(node)
18
+ # If we are at the root of the document, start the hash
19
+ if node.element?
20
+ if node.children?
21
+ result_hash = {}
22
+
23
+ node.each_child do |child|
24
+ result = xml_node_to_hash(child)
25
+
26
+ if child.name == "text"
27
+ if !child.next? and !child.prev?
28
+ return result
29
+ end
30
+ elsif result_hash[child.name]
31
+ if result_hash[child.name].is_a?(Object::Array)
32
+ result_hash[child.name] << result
33
+ else
34
+ result_hash[child.name] = [result_hash[child.name]] << result
35
+ end
36
+ else
37
+ result_hash[child.name] = result
38
+ end
39
+ end
40
+
41
+ return result_hash
42
+ else
43
+ return nil
44
+ end
45
+ else
46
+ return node.content.to_s
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,369 @@
1
+ require 'cgi'
2
+ require 'geo_certs/api_object'
3
+ require 'geo_certs/order/administrator'
4
+ require 'geo_certs/order/extended_validation_approver'
5
+ require 'geo_certs/order/organization'
6
+ require 'geo_certs/order/renewal_information'
7
+
8
+ module GeoCerts
9
+
10
+ ##
11
+ # Contains the details, attributes, and methods to interact with a GeoCerts order.
12
+ #
13
+ class Order < ApiObject
14
+
15
+ attr_accessor :approver_email,
16
+ :completed_at,
17
+ :created_at,
18
+ :domain,
19
+ :geotrust_order_id,
20
+ :id,
21
+ :licenses,
22
+ :sans,
23
+ :state,
24
+ :status_major,
25
+ :status_minor,
26
+ :total_price,
27
+ :years
28
+ attr_reader :administrator,
29
+ :csr,
30
+ :ev_approver,
31
+ :organization,
32
+ :pending_audit,
33
+ :product,
34
+ :renewal,
35
+ :renewal_information,
36
+ :trial
37
+
38
+ alias :approver= :approver_email=
39
+
40
+ force_boolean :pending_audit,
41
+ :renewal,
42
+ :trial
43
+
44
+ ##
45
+ # Returns all orders within the requested date range. By default the server will
46
+ # return orders within the past month (30 days).
47
+ #
48
+ # === Options
49
+ #
50
+ # :start_at:: The starting DateTime for the date range
51
+ # :end_at:: The ending DateTime for the date range
52
+ #
53
+ def self.all(options = {})
54
+ prep_date_ranges!(options)
55
+ response = call_api { GeoCerts.api.orders(options) }
56
+ build_collection(response) { |response| response[:orders][:order] }
57
+ end
58
+
59
+ ##
60
+ # Returns a GeoCerts order by the order +id+ given.
61
+ #
62
+ # === Exceptions
63
+ #
64
+ # If the +id+ cannot be found on the GeoCerts system, a GeoCerts::ResourceNotFound exception
65
+ # will be raised.
66
+ #
67
+ def self.find(id)
68
+ new(call_api { GeoCerts.api.find_order(:id => id)[:order] })
69
+ end
70
+
71
+ ##
72
+ # Similar to GeoCerts::Product.find, but instead of raising an exception when an order cannot
73
+ # be located, instead it will return +nil+.
74
+ #
75
+ # See GeoCerts::Product.find for more information.
76
+ #
77
+ def self.find_by_id(id)
78
+ find(id)
79
+ rescue GeoCerts::AllowableExceptionWithResponse
80
+ nil
81
+ end
82
+
83
+ def self.approvers(domain)
84
+ response = call_api { GeoCerts.api.domain_approvers(:domain => domain) }
85
+ collection = Collection.new
86
+ response[:emails][:email].each { |email| collection << Email.new(email) }
87
+ collection
88
+ end
89
+
90
+ ##
91
+ # Creates a new order on GeoCerts with the attributes given.
92
+ #
93
+ # This method will return an Order regardless of whether or not it was saved.
94
+ # You should check new_record? to determine whether or not there was a failure.
95
+ # Also, errors should not be empty if there was a failure.
96
+ #
97
+ def self.create(attributes = {}, &block)
98
+ object = new(attributes, &block)
99
+ object.save
100
+ object
101
+ end
102
+
103
+ ##
104
+ # Creates a new order on GeoCerts with the attributes given.
105
+ #
106
+ # === Exceptions
107
+ #
108
+ # This method will raise a GeoCerts::ResourceNotCreated exception if the order
109
+ # cannot be created.
110
+ #
111
+ def self.create!(attributes = {}, &block)
112
+ instance = create(attributes, &block)
113
+ raise(ResourceNotCreated, instance.errors.collect { |e| e.message }.join(', ')) if instance.new_record?
114
+ instance
115
+ end
116
+
117
+ ##
118
+ # Validates an order with the attributes provided. This method will also parse a given CSR
119
+ # body and populate the returned Order's CSR object with the parsed data.
120
+ #
121
+ # An Order will be returned whether or not validation was successful. To
122
+ # determine if validation was unsuccessful, you should check for errors
123
+ # (i.e. order.errors.empty? should be true).
124
+ #
125
+ def self.validate(attributes = {}, &block)
126
+ object = new(attributes, &block)
127
+ object.validate
128
+ object
129
+ end
130
+
131
+ ##
132
+ # See GeoCerts::Order.validate for more information.
133
+ #
134
+ # === Exceptions
135
+ #
136
+ # This method will raise GeoCerts::ResourceInvalid if the order is invalid.
137
+ #
138
+ def self.validate!(attributes = {}, &block)
139
+ instance = validate(attributes, &block)
140
+ raise(ResourceInvalid, instance.errors.collect { |e| e.message }.join(', ')) unless instance.errors.empty?
141
+ instance
142
+ end
143
+
144
+
145
+ ##
146
+ # Modifies the order state by setting it to the +action+ requested.
147
+ #
148
+ # Acceptable actions are: 'APPROVE' and 'CANCEL'
149
+ #
150
+ def modify!(action)
151
+ update_attributes(self.class.call_api {
152
+ GeoCerts.api.modify_order(:id => self.id, :state => action)
153
+ })
154
+ end
155
+
156
+ ##
157
+ # Instructs GeoCerts to resend the SSL certificate approval email to the
158
+ # approval address on the order.
159
+ #
160
+ def resend_approval_email!
161
+ update_attributes(self.class.call_api {
162
+ GeoCerts.api.resend_approval_email(:id => self.id)
163
+ })
164
+ end
165
+
166
+ ##
167
+ # Updates the approver email for the SSL certificate in the order.
168
+ #
169
+ def change_approver_email!(email)
170
+ update_attributes(self.class.call_api {
171
+ GeoCerts.api.change_order_approval_email(:id => self.id, :approver_email => email)
172
+ })
173
+ end
174
+
175
+ ##
176
+ # Validates the order attributes provided. You must, at least, provide a
177
+ # CSR and Product:
178
+ #
179
+ # GeoCerts::Order.new({
180
+ # :csr => "-----BEGIN CERTIFICATE REQUEST-----\n....",
181
+ # :product => 'QP'
182
+ # }).validate
183
+ #
184
+ # This method will return +false+ if the order is invalid. Details of the
185
+ # validation errors can be found in +errors+.
186
+ #
187
+ def validate
188
+ parameters = {}
189
+ parameters[:years] = self.years
190
+ parameters[:licenses] = self.licenses
191
+ parameters[:sans] = GeoCerts.escape(self.sans) if self.sans
192
+ parameters.merge!(self.csr.to_geocerts_hash) if self.csr
193
+ parameters.merge!(self.product.to_geocerts_hash) if self.product
194
+
195
+ update_attributes(self.class.call_api {GeoCerts.api.validate_order(parameters)[:order]})
196
+ rescue GeoCerts::AllowableExceptionWithResponse
197
+ store_exception_errors_and_warnings($!)
198
+ false
199
+ end
200
+
201
+ ##
202
+ # Acts similarly to +validate+, but will raise a GeoCerts::ResourceInvalid
203
+ # exception if validation fails.
204
+ #
205
+ def validate!
206
+ validate
207
+ raise(GeoCerts::ResourceInvalid) unless self.errors.empty?
208
+ self
209
+ end
210
+
211
+ ##
212
+ # Creates the order in the GeoCerts system. This will also deduct the cost of
213
+ # the order from your available balance.
214
+ #
215
+ # If the order cannot be created, this method will return +false+.
216
+ #
217
+ def save
218
+ new_record? ? create : raise("Cannot update an existing Order")
219
+ self.errors.empty? ? self : false
220
+ end
221
+
222
+ ##
223
+ # Acts similarly to +save+, but raises a GeoCerts::ResourceNotCreated exception
224
+ # if the order cannot be saved.
225
+ #
226
+ def save!
227
+ save ? self : raise(GeoCerts::ResourceNotCreated)
228
+ end
229
+
230
+ ##
231
+ # Returns +true+ if the Order has not been saved.
232
+ #
233
+ def new_record?
234
+ self.id.nil?
235
+ end
236
+
237
+ ##
238
+ # Sets the CSR for the order. You can either pass a GeoCerts::CSR object, or
239
+ # the body of a CSR.
240
+ #
241
+ # order.csr = GeoCerts::CSR.new(:body => "-----BEGIN CERTIFICATE REQUEST-----\n....")
242
+ # order.csr = "-----BEGIN CERTIFICATE REQUEST-----\n...."
243
+ #
244
+ def csr=(input)
245
+ @csr = case input
246
+ when CSR
247
+ input
248
+ when Hash
249
+ CSR.new(input)
250
+ when String
251
+ if input =~ /CERTIFICATE REQUEST-----/
252
+ CSR.new({:body => input})
253
+ else
254
+ raise ArgumentError.new("Unrecognized CSR given. Expected a CSR, Hash, or CSR body string, got: \"#{input.inspect}\"")
255
+ end
256
+ else
257
+ raise ArgumentError.new("Unrecognized CSR given. Expected a CSR, Hash, or CSR body string, got: \"#{input.inspect}\"")
258
+ end
259
+ end
260
+
261
+ ##
262
+ # Sets the renewal information for the order. This method accepts either
263
+ # a GeoCerts::RenewalInformation instance or a hash of attributes.
264
+ #
265
+ def renewal_information=(input)
266
+ case input
267
+ when RenewalInformation
268
+ @renewal_information = input
269
+ when Hash
270
+ @renewal_information = RenewalInformation.new(input)
271
+ end
272
+ end
273
+
274
+ ##
275
+ # Sets the product for the order. You can either pass a GeoCerts::Product
276
+ # object or the SKU for a GeoCerts product.
277
+ #
278
+ # order.product = GeoCerts::Product.new(:sku => 'QP')
279
+ # order.product = 'QP'
280
+ #
281
+ def product=(input)
282
+ @product = case input
283
+ when Product
284
+ input
285
+ when String
286
+ Product.find(input)
287
+ end
288
+ end
289
+
290
+ ##
291
+ # Sets the extended validation approver for the order. This method
292
+ # accepts either a GeoCerts::ExtendedValidationApprover instance or a
293
+ # hash of attributes.
294
+ #
295
+ def ev_approver=(input)
296
+ case input
297
+ when ExtendedValidationApprover
298
+ @ev_approver = input
299
+ when Hash
300
+ @ev_approver = ExtendedValidationApprover.new(input)
301
+ end
302
+ end
303
+
304
+ ##
305
+ # Sets the administrator for the order. This method accepts either a
306
+ # GeoCerts::Administrator instance or a hash of administrator attributes.
307
+ #
308
+ def administrator=(input)
309
+ case input
310
+ when Administrator
311
+ @administrator = input
312
+ when Hash
313
+ @administrator = Administrator.new(input)
314
+ end
315
+ end
316
+
317
+ ##
318
+ # Sets the organization for the order. This method accepts either a
319
+ # GeoCerts::Organization instance or a hash of organization attributes.
320
+ #
321
+ def organization=(input)
322
+ case input
323
+ when Organization
324
+ @organization = input
325
+ when Hash
326
+ @organization = Organization.new(input)
327
+ end
328
+ end
329
+
330
+ ##
331
+ # Returns a collection of events for the order.
332
+ #
333
+ def events
334
+ GeoCerts::Event.find_by_order_id(self.id)
335
+ end
336
+
337
+ ##
338
+ # Returns a GeoCerts::Certificate associated with this order.
339
+ #
340
+ def certificate
341
+ GeoCerts::Certificate.find_by_order_id(self.id)
342
+ end
343
+
344
+
345
+ private
346
+
347
+
348
+ def create
349
+ parameters = {}
350
+ parameters[:approver_email] = GeoCerts.escape(self.approver_email)
351
+ parameters[:years] = GeoCerts.escape(self.years)
352
+ parameters[:licenses] = GeoCerts.escape(self.licenses)
353
+ parameters[:sans] = GeoCerts.escape(self.sans)
354
+ parameters.merge!(self.csr.to_geocerts_hash) if self.csr
355
+ parameters.merge!(self.product.to_geocerts_hash) if self.product
356
+ parameters.merge!(self.ev_approver.to_geocerts_hash) if self.ev_approver
357
+ parameters.merge!(self.administrator.to_geocerts_hash) if self.administrator
358
+ parameters.merge!(self.organization.to_geocerts_hash) if self.organization
359
+
360
+ update_attributes(self.class.call_api {GeoCerts.api.create_order(parameters)[:order]})
361
+ self
362
+ rescue GeoCerts::AllowableExceptionWithResponse
363
+ store_exception_errors_and_warnings($!)
364
+ self
365
+ end
366
+
367
+ end
368
+
369
+ end