zuora_connect 2.1.1 → 3.0.0.pre.a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0342c5ac7396b4e8ba75aff8dbab5d579fa6d0ad04a421b7d1d809ab3abbd90a
4
- data.tar.gz: 70f7277a93fec8e481f63e56f85e466b5e0b4d1307e2413e4f8da9497e980be2
3
+ metadata.gz: e63c10c8405375ad7cb2c28073c6181ed055266fb8d61e3ac5725e8f5b8ca8d5
4
+ data.tar.gz: c5124fe3590fd14c0acdad0cfe6e567997195eaa728245f620bfff5bbda285fe
5
5
  SHA512:
6
- metadata.gz: eb6497a343dde2b4a3edfe470c8e5a44eb37ff99b75ed434138c280e8ac25bf36806d58fbb477772182596917f1c37c0e237bd55e88f646e149743477fba2f15
7
- data.tar.gz: f0b1f8b6f647f204ce8c4bfed7a8e77b49f3aada0faf6a0c31fc47675f5bfca67feb464692006bcb490977a577d1d5a3feab53886815f4c6472023e9ade6823b
6
+ metadata.gz: 1beb3e3c0531b3035051711670de269814122c20269086ffd31257b02dc4e6ff8c515ac812abc436360ebc9f1506e3ae8e15e859d6098913e08f2dfed67e1284
7
+ data.tar.gz: bff9fca90e302be4fe97b3cac4ac54bb8dc6c841ad6762939f9b0b2c6c7e66417bb108105d6d8372965ae9090d813c97cff8a4a4a6b513665beed63c9229f0e4
@@ -1,23 +1,20 @@
1
1
  module ZuoraConnect
2
2
  class StaticController < ApplicationController
3
- before_action :authenticate_connect_app_request, :except => [:metrics, :health, :initialize_app]
4
- before_action :clear_connect_app_session, :only => [:metrics, :health, :initialize_app]
5
- after_action :persist_connect_app_session, :except => [:metrics, :health, :initialize_app]
6
-
7
- skip_before_action :verify_authenticity_token, :only => [:initialize_app]
8
-
9
- def metrics
10
- type = params[:type].present? ? params[:type] : "versions"
11
- render json: ZuoraConnect::AppInstance.get_metrics(type).to_json, status: 200
12
- end
3
+ before_action :authenticate_connect_app_request, :except => [:health, :initialize_app, :provision, :instance_user]
4
+ before_action :clear_connect_app_session, :only => [:health, :initialize_app, :provision, :instance_user]
5
+ after_action :persist_connect_app_session, :except => [:health, :initialize_app, :provision, :instance_user]
6
+
7
+ skip_before_action :verify_authenticity_token, :only => [:initialize_app, :provision]
8
+ http_basic_authenticate_with name: ENV['PROVISION_USER'], password: ENV['PROVISION_SECRET'], :only => [:provision, :instance_user]
9
+
13
10
 
14
11
  def health
15
12
  if params[:error].present?
16
- begin
13
+ begin
17
14
  raise ZuoraConnect::Exceptions::Error.new('This is an error')
18
15
  rescue => ex
19
16
  case params[:error]
20
- when 'Log'
17
+ when 'Log'
21
18
  Rails.logger.error("Error in Health", ex)
22
19
  when 'Exception'
23
20
  raise
@@ -34,11 +31,13 @@ module ZuoraConnect
34
31
  def initialize_app
35
32
  begin
36
33
  authenticate_connect_app_request
37
- @appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
38
- render json: {
39
- message: "Success",
40
- status: 200
41
- }, status: 200
34
+ unless performed?
35
+ @appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
36
+ render json: {
37
+ message: 'Success',
38
+ status: 200
39
+ }, status: 200
40
+ end
42
41
  rescue => ex
43
42
  Rails.logger.error("Failed to Initialize application", ex)
44
43
  if performed?
@@ -52,6 +51,74 @@ module ZuoraConnect
52
51
  end
53
52
  end
54
53
 
54
+ def provision
55
+ create_new_instance
56
+ unless performed?
57
+ render json: {
58
+ status: 200,
59
+ message: 'Success',
60
+ app_instance_id: @appinstance.id
61
+ }, status: 200
62
+ end
63
+ rescue StandardError => e
64
+ message = 'Failed to provision new instance'
65
+ if performed?
66
+ Rails.logger.error("#{message}: #{performed?}", e)
67
+ else
68
+ Rails.logger.error(message, e)
69
+ render json: {
70
+ status: 500,
71
+ message: message
72
+ }, status: 500
73
+ end
74
+ end
75
+
76
+ def instance_user
77
+ ZuoraConnect::AppInstance.read_master_db do
78
+ ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
79
+ Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
80
+
81
+ if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
82
+ ElasticAPM.set_label(:trace_id, request.uuid)
83
+ end
84
+
85
+ unless params[:id].present?
86
+ render json: {
87
+ status: 400,
88
+ message: 'No app instance id provided'
89
+ }, status: :bad_request
90
+ return
91
+ end
92
+
93
+ @appinstance = ZuoraConnect::AppInstance.find(params[:id]).new_session
94
+ end
95
+
96
+ zuora_client = @appinstance.send(ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION).client
97
+ client_describe, = zuora_client.rest_call(
98
+ url: zuora_client.rest_endpoint('genesis/user/info').gsub('v1/', ''),
99
+ session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic
100
+ )
101
+
102
+ render json: {
103
+ status: 200,
104
+ message: 'Success',
105
+ user_id: client_describe['coreUserId'],
106
+ username: client_describe['username'],
107
+ email: client_describe['workEmail']
108
+ }, status: 200
109
+ rescue ActiveRecord::RecordNotFound
110
+ render json: {
111
+ status: 400,
112
+ message: 'No app instance found'
113
+ }, status: :bad_request
114
+ rescue StandardError => e
115
+ Rails.logger.error('Error occurred getting user details', e)
116
+ render json: {
117
+ status: 500,
118
+ message: 'Failed to get user details'
119
+ }, status: 500
120
+ end
121
+
55
122
  private
56
123
 
57
124
  def clear_connect_app_session
@@ -11,8 +11,7 @@ module ZuoraConnect
11
11
  before_destroy :prune_data
12
12
 
13
13
  self.table_name = "zuora_connect_app_instances"
14
- attr_accessor :options, :mode, :logins, :task_data, :last_refresh, :username, :password, :s3_client, :api_version, :drop_message, :new_session_message, :connect_user, :logitems
15
- @@telegraf_host = nil
14
+ attr_accessor :options, :mode, :logins, :task_data, :last_refresh, :username, :password, :s3_client, :api_version, :drop_message, :new_session_message, :connect_user, :logitems, :user_timezone
16
15
  REFRESH_TIMEOUT = 2.minute #Used to determine how long to wait on current refresh call before executing another
17
16
  INSTANCE_REFRESH_WINDOW = 1.hours #Used to set how how long till app starts attempting to refresh cached task connect data
18
17
  INSTANCE_REDIS_CACHE_PERIOD = 24.hours #Used to determine how long to cached task data will live for
@@ -21,6 +20,12 @@ module ZuoraConnect
21
20
  HOLDING_PATTERN_SLEEP = 5.seconds
22
21
  CONNECT_APPLICATION_ID = 0
23
22
  CONNECT_COMMUNICATION_SLEEP = Rails.env.test? ? 0.seconds : 5.seconds
23
+ CATALOG_LOOKUP_PAGE_SIZE = 10_000
24
+ CATALOG_LOOKUP_CACHE_TIME_KEY = 'CatalogCachedAt'
25
+ CATALOG_LOOKUP_TTL = 60.seconds
26
+ CATALOG_LOOKUP_CACHE_RESULT_KEY = 'CatalogCache'
27
+ TIMEZONE_LOG_RATE_LIMIT_KEY = 'TimezoneLoggedAt'
28
+ TIMEZONE_LOG_PERIOD = 4.hours
24
29
  IGNORED_LOCALS = ['fr', 'ja', 'es', 'zh', 'de']
25
30
  INTERNAL_HOSTS = []
26
31
  LOGIN_TENANT_DESTINATION = 'target_login'
@@ -29,7 +34,7 @@ module ZuoraConnect
29
34
  Aws::Errors::MissingCredentialsError,
30
35
  Aws::S3::Errors::AccessDenied,
31
36
  Aws::SES::Errors::AccessDenied,
32
- Aws::KMS::Errors::AccessDeniedException
37
+ Aws::KMS::Errors::AccessDeniedException
33
38
  ].freeze
34
39
  AWS_AUTH_ERRORS_MSG = "AWS Auth Errors".freeze
35
40
 
@@ -240,7 +245,9 @@ module ZuoraConnect
240
245
  rescue I18n::InvalidLocale => ex
241
246
  ZuoraConnect.logger.error(ex) if !IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
242
247
  end
243
- Time.zone = self.timezone
248
+
249
+ self.set_timezone
250
+
244
251
  if self.task_data.present?
245
252
  tenants = self.task_data.fetch('tenant_ids', [])
246
253
  organizations = self.task_data.fetch('organizations', [])
@@ -255,7 +262,7 @@ module ZuoraConnect
255
262
  end
256
263
 
257
264
  params = {
258
- name: self.task_data.dig('name'),
265
+ name: self.task_data.dig('name'),
259
266
  zuora_entity_ids: (self.task_data.dig(LOGIN_TENANT_DESTINATION,'entities') || []).map{|e| e['id']}.uniq,
260
267
  zuora_tenant_ids: tenants.map(&:to_s).uniq,
261
268
  organizations: organizations
@@ -264,7 +271,7 @@ module ZuoraConnect
264
271
  client = self.send(LOGIN_TENANT_DESTINATION).client
265
272
  if defined?(client.rest_domain)
266
273
  ZuoraConnect::RequestIdMiddleware.zuora_rest_domain = client.rest_domain
267
- params.merge!({zuora_domain: client.rest_domain, environment: client.environment })
274
+ params.merge!({zuora_domain: client.rest_domain, environment: client.environment })
268
275
  end
269
276
  end
270
277
  params = params.reject{|k,v| !self.attributes.keys.member?(k.to_s) || self[k] == v}
@@ -272,12 +279,80 @@ module ZuoraConnect
272
279
  end
273
280
  end
274
281
 
275
- def refresh(session: {})
282
+ def set_timezone(timezone: self.timezone, type: :default)
283
+ if timezone.blank?
284
+ timezone = self.timezone
285
+ end
286
+
287
+ if type == :default
288
+ Time.zone = timezone
289
+ elsif type == :user
290
+ begin
291
+ sql = <<-eos
292
+ SELECT zuora_users.zuora_identity_response
293
+ FROM "#{self.id}".zuora_users
294
+ ORDER BY zuora_users.updated_at DESC
295
+ LIMIT 1;
296
+ eos
297
+ user = ActiveRecord::Base.connection.execute(sql).to_a.first
298
+
299
+ if user.present?
300
+ zuora_identity_response = JSON.parse(user.fetch('zuora_identity_response', '{}'))
301
+ self.user_timezone = zuora_identity_response.values.first&.dig('timeZone')
302
+ else
303
+ if (Redis.current.hget(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id).to_i + TIMEZONE_LOG_PERIOD.to_i) <= Time.now.to_i
304
+ Rails.logger.error('Cannot find any user to set the timezone', app_instance_id: self.id)
305
+ Redis.current.hset(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id, Time.now.to_i)
306
+ end
307
+ end
308
+ rescue => ex
309
+ Rails.logger.error('There is an error while getting timezone users', ex)
310
+ end
311
+
312
+ if self.user_timezone.present?
313
+ # connect instance which has a custom timezone
314
+ if !self.auto_deployed? && (
315
+ ActiveSupport::TimeZone[self.task_data.dig('user_settings', 'timezone') || '']&.utc_offset !=
316
+ ActiveSupport::TimeZone[self.user_timezone]&.utc_offset
317
+ )
318
+ if self.environment == 'Production' &&
319
+ (Redis.current.hget(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id).to_i + TIMEZONE_LOG_PERIOD.to_i) <= Time.now.to_i
320
+ ZuoraConnect.logger.error(
321
+ "Instance and user timezones are different. User has '#{self.user_timezone}' and " \
322
+ "instance has '#{self.task_data.dig('user_settings', 'timezone')}'",
323
+ app_instance_id: self.id
324
+ )
325
+ Redis.current.hset(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id, Time.now.to_i)
326
+ end
327
+ self.user_timezone = nil
328
+ Time.zone = timezone
329
+ else
330
+ begin
331
+ Time.zone = self.user_timezone
332
+ rescue ArgumentError
333
+ Rails.logger.error('Malformed user timezone', app_instance_id: self.id)
334
+ Time.zone = timezone
335
+ end
336
+ end
337
+ else
338
+ Time.zone = timezone
339
+ end
340
+ end
341
+ rescue => e
342
+ Rails.logger.error('Malformed timezone used', e, app_instance_id: self.id)
343
+ Time.zone = self.timezone
344
+ end
345
+
346
+ def auto_deployed?
347
+ self.id >= 25000000
348
+ end
349
+
350
+ def refresh(session: {})
276
351
  refresh_count ||= 0
277
352
  skip_connect ||= false
278
353
  begin
279
354
  #Check how app was deployed
280
- if self.id < 25000000 && !skip_connect
355
+ if self.id < 25000000 && !skip_connect
281
356
  self.check_oauth_state
282
357
  response = HTTParty.get(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/tasks/#{self.id}.json",:body => {:access_token => self.access_token})
283
358
 
@@ -288,7 +363,7 @@ module ZuoraConnect
288
363
  raise ZuoraConnect::Exceptions::ConnectCommunicationError.new("JSON parse error", response.body, response.code)
289
364
  end
290
365
 
291
- self.build_task(task_data: parsed_json, session: session)
366
+ self.build_task(task_data: parsed_json, session: session)
292
367
  if self.kms_key.present? && self.kms_key.match(/^arn:aws:.*/)
293
368
  begin
294
369
  self.zuora_logins = self.strip_cache_data(object: parsed_json.dup, keys: ['applications', 'tokens', 'user_settings'])
@@ -298,7 +373,7 @@ module ZuoraConnect
298
373
  rescue => ex
299
374
  Rails.logger.error(AWS_AUTH_ERRORS_MSG, ex)
300
375
  end
301
- end
376
+ end
302
377
  else
303
378
  raise ZuoraConnect::Exceptions::ConnectCommunicationError.new("Error Communicating with Connect", response.body, response.code)
304
379
  end
@@ -338,6 +413,10 @@ module ZuoraConnect
338
413
  raise
339
414
  end
340
415
 
416
+ def aws_secrets
417
+ (Rails.application.secrets.aws || {}).transform_keys { |key| key.to_s }
418
+ end
419
+
341
420
  #### START KMS ENCRYPTION Methods ####
342
421
  def zuora_logins=(val)
343
422
  write_attribute(:zuora_logins, kms_encrypt(val.to_json))
@@ -350,7 +429,7 @@ module ZuoraConnect
350
429
 
351
430
  def kms_decrypt(value)
352
431
  kms_tries ||= 0
353
- kms_client = Aws::KMS::Client.new({region: Rails.application.secrets.aws['AWS_REGION'], credentials: self.aws_auth_client}.delete_if { |k, v| v.blank? })
432
+ kms_client = Aws::KMS::Client.new({region: aws_secrets['AWS_REGION'], credentials: self.aws_auth_client}.delete_if { |k, v| v.blank? })
354
433
  resp = kms_client.decrypt({ciphertext_blob: [value].pack("H*") })
355
434
  return resp.plaintext
356
435
  rescue *AWS_AUTH_ERRORS => ex
@@ -365,7 +444,7 @@ module ZuoraConnect
365
444
 
366
445
  def kms_encrypt(value)
367
446
  kms_tries ||= 0
368
- kms_client = Aws::KMS::Client.new({region: Rails.application.secrets.aws['AWS_REGION'], credentials: self.aws_auth_client}.delete_if {|k,v| v.blank? })
447
+ kms_client = Aws::KMS::Client.new({region: aws_secrets['AWS_REGION'], credentials: self.aws_auth_client}.delete_if {|k,v| v.blank? })
369
448
 
370
449
  resp = kms_client.encrypt({key_id: kms_key, plaintext: value})
371
450
  return resp.ciphertext_blob.unpack('H*').first
@@ -380,12 +459,12 @@ module ZuoraConnect
380
459
  end
381
460
 
382
461
  def kms_key
383
- return ENV['AWS_KMS_ARN'] || Rails.application.secrets.dig(:aws,'AWS_KMS_ARN')
462
+ return ENV['AWS_KMS_ARN'] || aws_secrets['AWS_KMS_ARN']
384
463
  end
385
464
 
386
465
  def aws_auth_client
387
466
  if Rails.env.to_s == 'development'
388
- return Aws::Credentials.new(Rails.application.secrets.aws['AWS_ACCESS_KEY_ID'], Rails.application.secrets.aws['AWS_SECRET_ACCESS_KEY'])
467
+ return Aws::Credentials.new(aws_secrets['AWS_ACCESS_KEY_ID'], aws_secrets['AWS_SECRET_ACCESS_KEY'])
389
468
  else
390
469
  return nil
391
470
  end
@@ -400,82 +479,6 @@ module ZuoraConnect
400
479
  end
401
480
  Thread.current[:appinstance] = self
402
481
  end
403
-
404
- def self.write_to_telegraf(*args)
405
- if ZuoraConnect.configuration.enable_metrics
406
- @@telegraf_host = ZuoraConnect::Telegraf.new() if @@telegraf_host == nil
407
- unicorn_stats = self.unicorn_listener_stats() if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
408
- @@telegraf_host.write(direction: 'Raindrops', tags: {}, values: unicorn_stats) unless unicorn_stats.blank?
409
- return @@telegraf_host.write(*args)
410
- end
411
- end
412
-
413
- def self.unicorn_listener_stats ()
414
- stats_hash = {}
415
- stats_hash["total_active"] = 0
416
- stats_hash["total_queued"] = 0
417
-
418
- begin
419
- tmp = Unicorn.listener_names
420
- unix = tmp.grep(%r{\A/})
421
- tcp = tmp.grep(/\A.+:\d+\z/)
422
- tcp = nil if tcp.empty?
423
- unix = nil if unix.empty?
424
-
425
-
426
- Raindrops::Linux.tcp_listener_stats(tcp).each do |addr,stats|
427
- stats_hash["active_#{addr}"] = stats.active
428
- stats_hash["queued_#{addr}"] = stats.queued
429
- stats_hash["total_active"] = stats.active + stats_hash["total_active"]
430
- stats_hash["total_queued"] = stats.queued + stats_hash["total_queued"]
431
- end if tcp
432
-
433
- Raindrops::Linux.unix_listener_stats(unix).each do |addr,stats|
434
- stats_hash["active_#{addr}"] = stats.active
435
- stats_hash["queued_#{addr}"] = stats.queued
436
- stats_hash["total_active"] = stats.active + stats_hash["total_active"]
437
- stats_hash["total_queued"] = stats.queued + stats_hash["total_queued"]
438
- end if unix
439
- rescue IOError => ex
440
- rescue => ex
441
- ZuoraConnect.logger.error(ex)
442
- end
443
- return stats_hash
444
- end
445
-
446
- def self.get_metrics(type)
447
- @data = {}
448
-
449
- if type == "versions"
450
- @data = {
451
- app_name: ZuoraConnect::Telegraf.app_name,
452
- url: "dummy",
453
- Version_Gem: ZuoraConnect::VERSION,
454
- Version_Zuora: ZuoraAPI::VERSION ,
455
- Version_Ruby: RUBY_VERSION,
456
- Version_Rails: Rails.version,
457
- hold: 1
458
- }
459
- elsif type == "stats"
460
- begin
461
- Resque.redis.ping
462
- @resque = Resque.info
463
- @data = {
464
- app_name: ZuoraConnect::Telegraf.app_name,
465
- url: "dummy",
466
- Resque:{
467
- Jobs_Finished: @resque[:processed] ,
468
- Jobs_Failed: @resque[:failed],
469
- Jobs_Pending: @resque[:pending],
470
- Workers_Active: @resque[:working],
471
- Workers_Total: @resque[:workers]
472
- }
473
- }
474
- rescue
475
- end
476
- end
477
- return @data
478
- end
479
482
  #### END Task Methods ####
480
483
 
481
484
  #### START Task Methods ####
@@ -518,7 +521,7 @@ module ZuoraConnect
518
521
  end
519
522
  rescue ZuoraConnect::Exceptions::MissMatch => ex
520
523
  raise
521
- rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
524
+ rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
522
525
  raise
523
526
  rescue => ex
524
527
  ZuoraConnect.logger.error("Build Task Error", ex)
@@ -574,10 +577,10 @@ module ZuoraConnect
574
577
  self.refresh if !defined?(self.target_login)
575
578
 
576
579
  response = HTTParty.get("#{ZuoraConnect.configuration.url}/api/#{self.api_version}/tenants/search?hostname=#{self.target_login.client.hostname}&node_id=#{self.zuora_entity_ids.first}")
577
-
580
+
578
581
  if response.success?
579
582
  parsed_json = JSON.parse(response.body)
580
-
583
+
581
584
  #Set Org
582
585
  if self.id >= 25000000 && parsed_json['organization'].present?
583
586
  login_cache = self.zuora_logins
@@ -599,7 +602,7 @@ module ZuoraConnect
599
602
  end
600
603
  end
601
604
  self.save(:validate => false)
602
-
605
+
603
606
  return parsed_json
604
607
  end
605
608
  rescue *(ZuoraAPI::Login::CONNECTION_EXCEPTIONS + ZuoraAPI::Login::CONNECTION_READ_EXCEPTIONS) => ex
@@ -653,7 +656,7 @@ module ZuoraConnect
653
656
  end
654
657
 
655
658
  def refresh_oauth
656
- refresh_oauth_count ||= 0
659
+ refresh_oauth_count ||= 0
657
660
  response = HTTParty.post("#{ZuoraConnect.configuration.url}/oauth/token", body: {
658
661
  :grant_type => "refresh_token",
659
662
  :redirect_uri => ZuoraConnect.configuration.oauth_client_redirect_uri,
@@ -955,13 +958,81 @@ module ZuoraConnect
955
958
  # object_id: The id or id's of the object/objects to be returned.
956
959
  # child_objects: Whether to include child objects of the object in question.
957
960
  # cache: Store individual "1" object lookup in redis for caching.
958
- def catalog_lookup(entity_id: nil, object: :product, object_id: nil, child_objects: false, cache: false)
961
+ def catalog_lookup(entity_id: nil, object: :product, object_id: nil, child_objects: false, cache: false, source: 'DB')
959
962
  entity_reference = entity_id.blank? ? 'Default' : entity_id
960
963
 
961
964
  if object_id.present? && ![Array, String].include?(object_id.class)
962
965
  raise "Object Id can only be a string or an array of strings"
963
966
  end
964
967
 
968
+ if source == 'API'
969
+ catalog_container = {}
970
+
971
+ if (Redis.current.hget(CATALOG_LOOKUP_CACHE_TIME_KEY, self.id).to_i + CATALOG_LOOKUP_TTL.to_i) > Time.now.to_i
972
+ begin
973
+ catalog_container = JSON.parse(Redis.current.hget(CATALOG_LOOKUP_CACHE_RESULT_KEY, self.id))
974
+ rescue JSON::ParserError => ex
975
+ Rails.logger.warn('Failed to parse catalog cache', ex)
976
+ end
977
+ else
978
+ zuora_login = self.login_lookup(type: 'Zuora').first
979
+ login = zuora_login.client(entity_reference)
980
+
981
+ response = {
982
+ 'nextPage' => login.rest_endpoint("catalog/products?pageSize=#{CATALOG_LOOKUP_PAGE_SIZE}")
983
+ }
984
+
985
+ while response['nextPage'].present?
986
+ url = login.rest_endpoint(response['nextPage'].split('/v1/').last)
987
+ output_json, response = login.rest_call(debug: false, url: url, timeout_retry: true)
988
+
989
+ case object
990
+ when :product
991
+ output_json.fetch('products', []).each do |product|
992
+ rate_plans = {}
993
+ product['productRatePlans'].each do |rate_plan|
994
+ charges = {}
995
+ rate_plan['productRatePlanCharges'].each do |charge|
996
+ charges[charge['id']] = charge.merge(
997
+ {
998
+ 'productId' => product['id'],
999
+ 'productName' => product['name'],
1000
+ 'productRatePlanId' => rate_plan['id'],
1001
+ 'productRatePlanName' => rate_plan['name'],
1002
+ }
1003
+ )
1004
+ end
1005
+
1006
+ rate_plan['productRatePlanCharges'] = charges
1007
+ rate_plans[rate_plan['id']] = rate_plan.merge(
1008
+ {
1009
+ 'productId' => product['id'],
1010
+ 'productName' => product['name']
1011
+ }
1012
+ )
1013
+ end
1014
+
1015
+ product['productRatePlans'] = rate_plans
1016
+ catalog_container[product['id']] = product
1017
+ end
1018
+ else
1019
+ raise "Available objects include [:product]"
1020
+ end
1021
+ end
1022
+
1023
+ Redis.current.hset(CATALOG_LOOKUP_CACHE_RESULT_KEY, self.id, catalog_container.to_json)
1024
+ Redis.current.hset(CATALOG_LOOKUP_CACHE_TIME_KEY, self.id, Time.now.to_i)
1025
+ end
1026
+
1027
+ if object_id.nil?
1028
+ catalog_container.transform_values! { |v| v.except('productRatePlans') }
1029
+ elsif object_id.is_a?(String)
1030
+ catalog_container = catalog_container[object_id]
1031
+ end
1032
+
1033
+ return catalog_container
1034
+ end
1035
+
965
1036
  if defined?(Redis.current) && object_id.present? && object_id.class == String && object_id.present?
966
1037
  stub_catalog = cache ? decrypt_data(data: Redis.current.get("Catalog:#{self.id}:#{object_id}:Children:#{child_objects}")) : nil
967
1038
  object_hierarchy = decrypt_data(data: Redis.current.get("Catalog:#{self.id}:#{object_id}:Hierarchy"))
@@ -1221,7 +1292,7 @@ module ZuoraConnect
1221
1292
 
1222
1293
  def self.without_sticking
1223
1294
  if self.connection.respond_to?(:without_sticking)
1224
- self.connection.without_sticking do
1295
+ self.connection.without_sticking do
1225
1296
  yield
1226
1297
  end
1227
1298
  else