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 +4 -4
- data/lib/zuora_api/login.rb +265 -24
- data/lib/zuora_api/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf22e129425646f0333a0fbfba46454caed076d8
|
4
|
+
data.tar.gz: 8bef1bdcdc8d148b6450846f8d8fc014f6964543
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7f61fe146b9593d91315f95e91dbc073229b80e71274630c76b5c30d099b12ed4b282c54cdac7106bb02141f490cfd2d2df8d881623af200be415435d77070f
|
7
|
+
data.tar.gz: 7a4e6c34d8c7019c1d1d474b7c946db1d85b075ea173bc4571fb29ae15d28113857002e5ec03f809b8c681e4dc8345f80840adede4f5ff899e931eddaac2b636
|
data/lib/zuora_api/login.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
259
|
+
elsif /(?<=\.|\/|-|^)(pt[\d]*)(?=\.|\/|-|$)/ === self.hostname
|
72
260
|
self.environment = 'Performance'
|
73
|
-
elsif
|
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
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
data/lib/zuora_api/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2018-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|