zuora_api 1.6.15 → 1.6.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9c9111752188cb90238bb392e0aae06b418b8ed
4
- data.tar.gz: 7ef09b01663e686f0ca345df80d811dbb6985f51
3
+ metadata.gz: cf22e129425646f0333a0fbfba46454caed076d8
4
+ data.tar.gz: 8bef1bdcdc8d148b6450846f8d8fc014f6964543
5
5
  SHA512:
6
- metadata.gz: 98acc03915f4858ea36879443524d29787cbc3b3cf910fad20c512c3dbbdbc65c77de6e53e6bb131738af2e43f20d1411fb693f41bc4e586cf76ca1f801eca93
7
- data.tar.gz: 1e750f3eb7156be665471ccac1a374f8fbc3b399388aa61670a590d837c2b6984202d37bc1bdfacc9527cdce58ec46b4d02acb56df80b1e36046ceac147b3078
6
+ metadata.gz: b7f61fe146b9593d91315f95e91dbc073229b80e71274630c76b5c30d099b12ed4b282c54cdac7106bb02141f490cfd2d2df8d881623af200be415435d77070f
7
+ data.tar.gz: 7a4e6c34d8c7019c1d1d474b7c946db1d85b075ea173bc4571fb29ae15d28113857002e5ec03f809b8c681e4dc8345f80840adede4f5ff899e931eddaac2b636
@@ -4,23 +4,200 @@ require "uri"
4
4
 
5
5
  module ZuoraAPI
6
6
  class Login
7
- ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown' ]
7
+ ENVIRONMENTS = [SANDBOX = 'Sandbox', PRODUCTION = 'Production', PREFORMANCE = 'Preformance', SERVICES = 'Services', UNKNOWN = 'Unknown', STAGING = 'Staging' ]
8
8
  REGIONS = [EU = 'EU', US = 'US', NA = 'NA' ]
9
9
  MIN_Endpoint = '91.0'
10
10
  XML_SAVE_OPTIONS = Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
11
- attr_accessor :region, :url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep
11
+ attr_accessor :region, :url, :wsdl_number, :current_session, :environment, :status, :errors, :current_error, :user_info, :tenant_id, :tenant_name, :entity_id, :timeout_sleep, :hostname, :zconnect_provider
12
12
 
13
13
  def initialize(url: nil, entity_id: nil, session: nil, status: nil, **keyword_args)
14
+ raise "URL is nil or empty, but URL is required" if url.nil? | url.empty?
15
+ # raise "URL is improper. URL must contain zuora.com, zuora.eu, or zuora.na" if /zuora.com|zuora.eu|zuora.na/ === url
14
16
  @url = url.gsub(/(\d{2}\.\d)$/, MIN_Endpoint)
17
+ @hostname = /(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url)[0] if !/(?<=https:\/\/|http:\/\/)(.*?)(?=\/|$)/.match(url).nil?
15
18
  @entity_id = get_entity_id(entity_id: entity_id)
16
19
  @errors = Hash.new
17
20
  @current_session = session
18
21
  @status = status.blank? ? "Active" : status
19
22
  @user_info = Hash.new
23
+ self.update_region
20
24
  self.update_environment
25
+ self.update_zconnect_provider
21
26
  @timeout_sleep = 5
22
27
  end
23
28
 
29
+ def get_identity(cookies)
30
+ zsession = cookies["ZSession"]
31
+ zconnect_accesstoken = get_zconnect_accesstoken(cookies)
32
+ begin
33
+ if false && !zsession.blank?
34
+ # Does not currently exist / function properly
35
+ # use the zsession API when/if it exists
36
+ elsif !zconnect_accesstoken.blank?
37
+ code = zconnect_accesstoken.split("#!").last
38
+ encrypted_token, tenant_id = Base64.decode64(code).split(":")
39
+ begin
40
+ body = {'token' => encrypted_token}.to_json
41
+ rescue => ex
42
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Invalid ZConnect Cookie", {}, 400)
43
+ end
44
+ response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/identity", :body => body, :headers => { 'Content-Type' => 'application/json' })
45
+ output_json = JSON.parse(response.body)
46
+ else
47
+ if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
48
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
49
+ else
50
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
51
+ end
52
+ end
53
+ rescue JSON::ParserError => ex
54
+ output_json = {}
55
+ end
56
+ raise_errors(type: :JSON, body: output_json, response: response)
57
+ return output_json
58
+ end
59
+
60
+ def get_full_nav(cookies)
61
+ zsession = cookies["ZSession"]
62
+ zconnect_accesstoken = get_zconnect_accesstoken(cookies)
63
+ begin
64
+ if !zsession.blank?
65
+ response = HTTParty.get("https://#{self.hostname}/apps/v1/navigation", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
66
+ output_json = JSON.parse(response.body)
67
+ elsif !zconnect_accesstoken.blank?
68
+ response = HTTParty.get("https://#{self.hostname}/apps/zconnectsession/navigation", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}",'Content-Type' => 'application/json'})
69
+ output_json = JSON.parse(response.body)
70
+ else
71
+ if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
72
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
73
+ else
74
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
75
+ end
76
+ end
77
+ rescue JSON::ParserError => ex
78
+ output_json = {}
79
+ end
80
+ raise_errors(type: :JSON, body: output_json, response: response)
81
+ return output_json
82
+ end
83
+
84
+ def set_nav(state, cookies)
85
+ zsession = cookies["ZSession"]
86
+ zconnect_accesstoken = get_zconnect_accesstoken(cookies)
87
+ begin
88
+ if !zsession.blank?
89
+ response = HTTParty.put("https://#{self.hostname}/apps/v1/preference/navigation", :body => state.to_json, :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
90
+ output_json = JSON.parse(response.body)
91
+ elsif !zconnect_accesstoken.blank?
92
+ response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/navigationstate", :body => state.to_json, :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
93
+ output_json = JSON.parse(response.body)
94
+ else
95
+ if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
96
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
97
+ else
98
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
99
+ end
100
+ end
101
+ rescue JSON::ParserError => ex
102
+ output_json = {}
103
+ end
104
+ raise_errors(type: :JSON, body: output_json, response: response)
105
+ return output_json
106
+ end
107
+
108
+ def refresh_nav(cookies)
109
+ zsession = cookies["ZSession"]
110
+ zconnect_accesstoken = get_zconnect_accesstoken(cookies)
111
+ begin
112
+ if !zsession.blank?
113
+ response = HTTParty.post("https://#{self.hostname}/apps/v1/navigation/fetch", :headers => {'Cookie' => "ZSession=#{zsession}", 'Content-Type' => 'application/json'})
114
+ output_json = JSON.parse(response.body)
115
+ elsif !zconnect_accesstoken.blank?
116
+ response = HTTParty.post("https://#{self.hostname}/apps/zconnectsession/refresh-navbarcache", :headers => {'Cookie' => "#{self.zconnect_provider}=#{zconnect_accesstoken}", 'Content-Type' => 'application/json'})
117
+ output_json = JSON.parse(response.body)
118
+ else
119
+ if zconnect_accesstoken.blank? && cookies.keys.any? { |x| x.include? "ZConnect"}
120
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZConnect cookie present matching #{self.hostname}", {}, 400)
121
+ else
122
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("No ZSession cookie present", {}, 400)
123
+ end
124
+ end
125
+ rescue JSON::ParserError => ex
126
+ output_json = {}
127
+ end
128
+ raise_errors(type: :JSON, body: output_json, response: response)
129
+ return output_json
130
+ end
131
+
132
+ def get_zconnect_accesstoken(cookies)
133
+ accesstoken = nil
134
+ self.update_zconnect_provider
135
+ if !cookies[self.zconnect_provider].nil? && !cookies[self.zconnect_provider].empty?
136
+ accesstoken = cookies[self.zconnect_provider]
137
+ end
138
+ return accesstoken
139
+ end
140
+
141
+ def reporting_url(path)
142
+ map = {"US" => {"Sandbox" => "https://zconnectsandbox.zuora.com/api/rest/v1/",
143
+ "Production" => "https://zconnect.zuora.com/api/rest/v1/",
144
+ "Services"=> ""},
145
+ "EU" => {"Sandbox" => "https://zconnect.sandbox.eu.zuora.com/api/rest/v1/",
146
+ "Production" => "https://zconnect.eu.zuora.com/api/rest/v1/",
147
+ "Services"=> ""},
148
+ "NA" => {"Sandbox" => "https://zconnect.sandbox.na.zuora.com/api/rest/v1/",
149
+ "Production" => "https://zconnect.na.zuora.com/api/rest/v1/",
150
+ "Services"=> ""}
151
+ }
152
+ return map[zuora_client.region][zuora_client.environment].insert(-1, path)
153
+ end
154
+
155
+ # There are two ways to call this method. The first way is best.
156
+ # 1. Pass in cookies and optionally custom_authorities, name, and description
157
+ # 2. Pass in user_id, entity_ids, client_id, client_secret, and optionally custom_authorities, name, and description
158
+ # https://intranet.zuora.com/confluence/display/Sunburst/Create+an+OAuth+Client+through+API+Gateway#CreateanOAuthClientthroughAPIGateway-ZSession
159
+ def get_oauth_client (custom_authorities = [], info_name: "No Name", info_desc: "This client was created without a description.", user_id: nil, entity_ids: nil, client_id: nil, client_secret: nil, new_client_id: nil, new_client_secret: nil, cookies: nil)
160
+ authorization = ""
161
+ new_client_id = SecureRandom.uuid if new_client_id.blank?
162
+ new_client_secret = SecureRandom.hex(10) if new_client_secret.blank?
163
+
164
+ if !cookies.nil?
165
+ authorization = cookies["ZSession"]
166
+ authorization = "ZSession-a3N2w #{authorization}"
167
+ if entity_ids.blank? && cookies["ZuoraCurrentEntity"].present?
168
+ entity_ids = Array(cookies["ZuoraCurrentEntity"].unpack("a8a4a4a4a12").join('-'))
169
+ else
170
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora Entity ID not provided", {}, 400)
171
+ end
172
+ if user_id.blank? && cookies["Zuora-User-Id"].present?
173
+ user_id = cookies["Zuora-User-Id"]
174
+ else
175
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Zuora User ID not provided", {}, 400)
176
+ end
177
+ elsif !client_id.nil? && !client_secret.nil?
178
+ bearer_response = HTTParty.post("https://#{self.hostname}/oauth/token", :headers => {'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => 'application/json'}, :body => {'client_id' => client_id, 'client_secret' => URI::encode(client_secret), 'grant_type' => 'client_credentials'})
179
+ bearer_hash = JSON.parse(bearer_response.body)
180
+ bearer_token = bearer_hash["access_token"]
181
+ authorization = "Bearer #{bearer_token}"
182
+ end
183
+
184
+ if !authorization.blank? && !user_id.blank? && !entity_ids.blank?
185
+ endpoint = self.rest_endpoint("genesis/clients")
186
+ oauth_response = HTTParty.post(endpoint, :headers => {'authorization' => authorization, 'Content-Type' => 'application/json'}, :body => {'clientId' => new_client_id, 'clientSecret' => new_client_secret, 'userId' => user_id, 'entityIds' => entity_ids, 'customAuthorities' => custom_authorities, 'additionalInformation' => {'description' => info_desc, 'name' => info_name}}.to_json)
187
+ output_json = JSON.parse(oauth_response.body)
188
+ if oauth_response.code == 201
189
+ output_json["clientSecret"] = new_client_secret
190
+ return output_json
191
+ elsif oauth_response.code == 401 && !oauth_response.message.blank?
192
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["message"], {}, oauth_response.code)
193
+ else
194
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(output_json["error"], {}, oauth_response.code)
195
+ end
196
+ else
197
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new("Insufficient credentials provided", {}, 400)
198
+ end
199
+ end
200
+
24
201
  def self.environments
25
202
  %w(Sandbox Production Services Performance Staging)
26
203
  end
@@ -58,45 +235,105 @@ module ZuoraAPI
58
235
  return entity_id
59
236
  end
60
237
 
238
+ def update_region
239
+ if !self.hostname.blank?
240
+ if /(?<=\.|\/|^)(eu)(?=\.|\/|$)/ === self.hostname
241
+ self.region = "EU"
242
+ elsif /(?<=\.|\/|^)(na)(?=\.|\/|$)/ === self.hostname
243
+ self.region = "NA"
244
+ else
245
+ self.region = "US"
246
+ end
247
+ else # This will never happen
248
+ # raise "Can't update region because URL is blank"
249
+ self.region = "Unknown"
250
+ end
251
+ end
252
+
61
253
  def update_environment
62
254
  if !self.url.blank?
63
- env_path = self.url.split('https://').last.split('.zuora.com').first
64
- self.region = self.url.include?("eu.") ? "EU" : self.url.include?("na.") ? "NA" : "US"
65
- if env_path == 'apisandbox' || self.url.include?('sandbox')
255
+ if /(?<=\.|\/|-|^)(apisandbox|sandbox)(?=\.|\/|-|$)/ === self.hostname
66
256
  self.environment = 'Sandbox'
67
- elsif env_path == 'www' || env_path == 'api' || self.url.include?('tls10.zuora.com') || self.url.include?('origin-www.zuora.com') || self.url.include?('zforsf.zuora.com') || self.url.include?('https://zuora.com') || self.url.include?('eu.zuora.com') || self.url.include?('https://na.zuora.com')
68
- self.environment = 'Production'
69
- elsif env_path.include?('service') || env_path.include?('ep-edge')
257
+ elsif /(?<=\.|\/|^)(service|services[\d]*|ep-edge)(?=\.|\/|$)/ === self.hostname
70
258
  self.environment = 'Services'
71
- elsif env_path.include?('pt')
259
+ elsif /(?<=\.|\/|-|^)(pt[\d]*)(?=\.|\/|-|$)/ === self.hostname
72
260
  self.environment = 'Performance'
73
- elsif env_path.include?('staging2') || env_path.include?('staging1')
74
- self.region = 'US'
261
+ elsif /(?<=\.|\/|^)(staging1|staging2|stg)(?=\.|\/|$)/ === self.hostname
75
262
  self.environment = 'Staging'
263
+ elsif is_prod_env
264
+ self.environment = 'Production'
76
265
  else
77
266
  self.environment = 'Unknown'
78
267
  end
268
+ else # this will never happen
269
+ raise "Can't determine environment from blank URL"
270
+ end
271
+ end
272
+
273
+ def is_prod_env
274
+ is_prod = false
275
+ www_or_api = /(?<=\.|\/|^)(www|api)(?=\.|\/|$)/ === self.hostname
276
+ host_prefix_match = /(^|tls10\.|origin-www\.|zforsf\.|eu\.|na\.)(zuora\.com)/ === self.hostname
277
+ if www_or_api || host_prefix_match
278
+ is_prod = true
79
279
  end
280
+ return is_prod
281
+ end
282
+
283
+ def update_zconnect_provider
284
+ region = update_region
285
+ environment = update_environment
286
+ mappings = {"US" => {"Sandbox" => "ZConnectSbx", "KubeSTG" => "ZConnectDev", "KubeDEV" => "ZConnectDev", "KubePROD" => "ZConnectDev", "Services" => "ZConnectQA", "Production" => "ZConnectProd", "Performance" => "ZConnectPT1", "Staging" => "ZConnectQA"},
287
+ "NA" => {"Sandbox" => "ZConnectSbxNA", "Services" => "ZConnectQANA", "Production" => "ZConnectProdNA", "Performance" => "ZConnectPT1NA"},
288
+ "EU" => {"Sandbox" => "ZConnectSbxEU", "Services" => "ZConnectQAEU", "Production" => "ZConnectProdEU", "Performance" => "ZConnectPT1EU"},
289
+ "Unknown" => {"Unknown" => "Unknown"}}
290
+ self.zconnect_provider = mappings[region][environment]
291
+ # raise "Can't find ZConnect Provider for #{region} region and #{environment} environment" if self.zconnect_provider.nil?
80
292
  end
81
293
 
82
294
  def aqua_endpoint(url="")
83
- return "#{self.url.split("/apps").first}/apps/api/".concat(url)
295
+ match = /.*(\/apps\/)/.match(self.url)
296
+ if !match.nil?
297
+ url_slash_apps_slash = match[0]
298
+ else
299
+ raise "self.url has no /apps in it"
300
+ end
301
+ return "#{url_slash_apps_slash}api/#{url}"
84
302
  end
85
303
 
86
304
  def rest_endpoint(url="")
87
- if self.environment == 'Sandbox'
88
- return self.region == "US" ? "https://rest.apisandbox.zuora.com/v1/".concat(url) : self.region == "EU" ? "https://rest.sandbox.eu.zuora.com/v1/".concat(url) : "https://rest.sandbox.na.zuora.com/v1/".concat(url)
89
- elsif self.environment == 'Production'
90
- return self.region == "US" ? "https://rest.zuora.com/v1/".concat(url) : self.region == "EU" ? "https://rest.eu.zuora.com/v1/".concat(url) : "https://rest.na.zuora.com/v1/".concat(url)
91
- elsif self.environment == 'Services'
92
- return self.url.split('/')[0..2].join('/').concat('/apps/v1/').concat(url)
93
- elsif self.environment == 'Performance'
94
- return self.url.split('/')[0..2].join('/').concat('/apps/v1/').concat(url)
95
- elsif self.environment == 'Staging'
96
- return "https://rest-staging2.zuora.com/v1/".concat(url)
97
- else self.environment == 'Unknown'
98
- return url
305
+ update_environment
306
+ endpoint = url
307
+
308
+ case self.environment
309
+ when 'Sandbox'
310
+ case self.region
311
+ when 'US'
312
+ endpoint = "https://rest.apisandbox.zuora.com/v1/".concat(url)
313
+ when 'EU'
314
+ endpoint = "https://rest.sandbox.eu.zuora.com/v1/".concat(url)
315
+ when 'NA'
316
+ endpoint = "https://rest.sandbox.na.zuora.com/v1/".concat(url)
317
+ end
318
+ when 'Production'
319
+ case self.region
320
+ when 'US'
321
+ endpoint = "https://rest.zuora.com/v1/".concat(url)
322
+ when 'EU'
323
+ endpoint = "https://rest.eu.zuora.com/v1/".concat(url)
324
+ when 'NA'
325
+ endpoint = "https://rest.na.zuora.com/v1/".concat(url)
326
+ end
327
+ when 'Services', 'Performance'
328
+ https = /https:\/\/|http:\/\//.match(self.url)[0]
329
+ host = self.hostname
330
+ endpoint = "#{https}#{host}/apps/v1/#{url}"
331
+ when 'Staging'
332
+ endpoint = "https://rest-staging2.zuora.com/".concat(url)
333
+ when 'Unknown'
334
+ raise "Environment unknown, returning passed in parameter unaltered"
99
335
  end
336
+ return endpoint
100
337
  end
101
338
 
102
339
  def fileURL(url="")
@@ -282,6 +519,10 @@ module ZuoraAPI
282
519
  raise ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError.new()
283
520
  end
284
521
 
522
+ if body['errorMessage']
523
+ raise ZuoraAPI::Exceptions::ZuoraAPIError.new(body['errorMessage'],body,response.code)
524
+ end
525
+
285
526
  if body.dig("reasons").nil? ? false : body.dig("reasons")[0].dig("code") == 90000020
286
527
  raise ZuoraAPI::Exceptions::BadEntityError.new("#{messages_array.join(', ')}", body, response.code)
287
528
  end
@@ -1,3 +1,3 @@
1
1
  module ZuoraAPI
2
- VERSION = "1.6.15"
2
+ VERSION = "1.6.16"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zuora_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.15
4
+ version: 1.6.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zuora Strategic Solutions Group
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-04 00:00:00.000000000 Z
11
+ date: 2018-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler