zuora_connect 2.0.60r → 2.1.1

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.
@@ -3,93 +3,38 @@ if defined? Prometheus
3
3
  require "zuora_connect/version"
4
4
  require "zuora_api/version"
5
5
 
6
- resque_path = "#{ENV['RESQUE_EXPORTER_PATH'] || Rails.root.join('tmp/resque_exporter')}/*.prom"
7
- prometheus_path = Rails.root.join("tmp/prometheus")
8
-
9
- Dir[resque_path, "#{prometheus_path}/*.bin"].each do |file_path|
10
- File.unlink(file_path)
11
- end
12
-
13
- require 'prometheus/client/data_stores/direct_file_store'
14
- Prometheus::Client.config.data_store = Prometheus::Client::DataStores::DirectFileStore.new(
15
- dir: prometheus_path
16
- )
17
-
18
- class ResqueExporter
19
- require 'prometheus/client/formats/text'
20
- require 'fileutils'
21
-
22
- def initialize
23
- @lock = Monitor.new
24
- @registry = Prometheus::Client.registry
25
- @path = ENV['RESQUE_EXPORTER_PATH'] || Rails.root.join('tmp/resque_exporter')
26
- FileUtils.mkdir_p(@path)
27
- end
28
-
29
- def export
30
- filename = File.join(@path, "resque_export_#{Process.pid}.prom")
31
- @lock.synchronize do
32
- File.open(filename, 'w+') do |file|
33
- file.write(Prometheus::Client::Formats::Text.marshal(@registry))
34
- end
35
- end
36
- end
37
- end
38
-
39
- most_recent_aggregation = {}
40
- sum_aggregation = {}
41
- if defined?(Unicorn)
42
- most_recent_aggregation[:aggregation] = :most_recent
43
- sum_aggregation[:aggregation] = :sum
44
- end
45
-
46
6
  # Create a default Prometheus registry for our metrics.
47
7
  prometheus = Prometheus::Client.registry
48
8
 
49
9
  # Create your metrics.
50
- ZUORA_VERSION = prometheus.gauge(:zuora_version, docstring: 'The current Zuora Gem version.', labels: %i(version name), preset_labels: { version: ZuoraAPI::VERSION, name: ZuoraConnect::Telegraf.app_name }, store_settings: most_recent_aggregation)
51
- CONNECT_VERSION = prometheus.gauge(:gem_version, docstring: 'The current Connect Gem version.', labels: %i(version name), preset_labels: { version: ZuoraConnect::VERSION, name: ZuoraConnect::Telegraf.app_name }, store_settings: most_recent_aggregation)
52
- RAILS_VERSION = prometheus.gauge(:rails_version, docstring: 'The current Rails version.', labels: %i(version name), preset_labels: { version: Rails.version, name: ZuoraConnect::Telegraf.app_name }, store_settings: most_recent_aggregation)
53
- RUBY_V = prometheus.gauge(:ruby_version, docstring: 'The current Ruby version.', labels: %i(version name), preset_labels: { version: RUBY_VERSION, name: ZuoraConnect::Telegraf.app_name }, store_settings: most_recent_aggregation)
10
+ ZUORA_VERSION = Prometheus::Client::Gauge.new(:zuora_version, 'The current Zuora Gem version.')
11
+ CONNECT_VERSION = Prometheus::Client::Gauge.new(:gem_version, 'The current Connect Gem version.')
12
+ RAILS_VERSION = Prometheus::Client::Gauge.new(:rails_version, 'The current Rails version.')
13
+ RUBY_V = Prometheus::Client::Gauge.new(:ruby_version, 'The current Ruby version.')
54
14
 
55
- ZUORA_VERSION.set(0)
56
- CONNECT_VERSION.set(0)
57
- RAILS_VERSION.set(0)
58
- RUBY_V.set(0)
15
+ # Register your metrics with the registry we previously created.
16
+ prometheus.register(ZUORA_VERSION);ZUORA_VERSION.set({version: ZuoraAPI::VERSION, name: ZuoraConnect::Telegraf.app_name},0)
17
+ prometheus.register(CONNECT_VERSION);CONNECT_VERSION.set({version: ZuoraConnect::VERSION, name: ZuoraConnect::Telegraf.app_name},0)
18
+ prometheus.register(RAILS_VERSION);RAILS_VERSION.set({version: Rails.version, name: ZuoraConnect::Telegraf.app_name},0)
19
+ prometheus.register(RUBY_V);RUBY_V.set({version: RUBY_VERSION, name: ZuoraConnect::Telegraf.app_name},0)
59
20
 
60
21
  # Do they have resque jobs?
61
22
  if defined? Resque.redis
62
- REDIS_CONNECTION = prometheus.gauge(:redis_connection, docstring: 'The status of the redis connection, 0 or 1', labels: %i(connection name), preset_labels: {connection:'redis', name: ZuoraConnect::Telegraf.app_name}, store_settings: most_recent_aggregation)
63
- JOBS_FINISHED = prometheus.gauge(:jobs_finished, docstring: 'Done resque jobs', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraConnect::Telegraf.app_name}, store_settings: most_recent_aggregation)
64
- WORKERS_TOTAL = prometheus.gauge(:workers_total, docstring: 'Total resque workers', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraConnect::Telegraf.app_name}, store_settings: most_recent_aggregation)
65
- WORKERS_ACTIVE = prometheus.gauge(:workers_active, docstring: 'Active resque workers', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraConnect::Telegraf.app_name}, store_settings: most_recent_aggregation)
66
- JOBS_FAILED = prometheus.gauge(:jobs_failed, docstring: 'Failed resque jobs', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraConnect::Telegraf.app_name}, store_settings: most_recent_aggregation)
67
- JOBS_PENDING = prometheus.gauge(:jobs_pending, docstring: 'Pending resque jobs', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraConnect::Telegraf.app_name}, store_settings: most_recent_aggregation)
68
- end
69
-
70
- if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
71
- UNICORN_KILLS = prometheus.gauge(
72
- :unicorn_kills,
73
- docstring: 'Unicorn Kills',
74
- labels: %i(type name),
75
- preset_labels: {type:'Unicorn-Killer', name: ZuoraConnect::Telegraf.app_name},
76
- store_settings: sum_aggregation
77
- )
23
+ REDIS_CONNECTION = Prometheus::Client::Gauge.new(:redis_connection, 'The status of the redis connection, 0 or 1')
24
+ FINISHED_JOBS = Prometheus::Client::Gauge.new(:finished_jobs, 'Done resque jobs')
25
+ WORKERS = Prometheus::Client::Gauge.new(:workers, 'Total resque workers')
26
+ ACTIVE_WORKERS = Prometheus::Client::Gauge.new(:active_workers, 'Active resque workers')
27
+ FAILED_JOBS = Prometheus::Client::Gauge.new(:failed_jobs, 'Failed resque jobs')
28
+ PENDING_JOBS = Prometheus::Client::Gauge.new(:pending_jobs, 'Pending resque jobs')
29
+
30
+ prometheus.register(REDIS_CONNECTION)
31
+ prometheus.register(FINISHED_JOBS)
32
+ prometheus.register(ACTIVE_WORKERS)
33
+ prometheus.register(WORKERS)
34
+ prometheus.register(FAILED_JOBS)
35
+ prometheus.register(PENDING_JOBS)
78
36
 
79
- ZuoraConnect::AppInstanceBase.unicorn_listener_stats.each do |key, _|
80
- gauge_name = "unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_')
81
- gauge = prometheus.gauge(
82
- gauge_name.to_sym,
83
- docstring: 'Unicorn Stats',
84
- labels: %i(type name),
85
- preset_labels: { type: 'unicorn', name: ZuoraConnect::Telegraf.app_name },
86
- store_settings: most_recent_aggregation
87
- )
88
- Prometheus.const_set(
89
- gauge_name.upcase,
90
- gauge
91
- )
92
- end
93
37
  end
38
+
94
39
  end
95
40
  end
@@ -5,20 +5,6 @@ if defined?(Resque::Worker)
5
5
  Resque::Job.send(:include, Resque::SelfLookup)
6
6
  end
7
7
 
8
- if defined?(Resque::Job) && defined?(Prometheus)
9
- module ResquePrometheusExtensions
10
- EXPORTER = Prometheus::ResqueExporter.new
11
- def perform
12
- super
13
- EXPORTER.export
14
- end
15
- end
16
-
17
- class Resque::Job
18
- prepend ResquePrometheusExtensions
19
- end
20
- end
21
-
22
8
  Resque.module_eval do
23
9
  # Returns a hash, mapping queue names to queue sizes
24
10
  def queue_sizes
@@ -3,35 +3,7 @@ if defined?(Unicorn::WorkerKiller)
3
3
  self.singleton_class.send(:alias_method, :kill_self_old, :kill_self)
4
4
  def self.kill_self(logger, start_time)
5
5
  self.kill_self_old(logger, start_time)
6
- if defined?(Prometheus)
7
- Prometheus::UNICORN_KILLS.set(1)
8
- else
9
- ZuoraConnect::AppInstance.write_to_telegraf(direction: 'Unicorn-Killer', tags: {app_instance: 0}, values: {kill: 1})
10
- end
6
+ ZuoraConnect::AppInstance.write_to_telegraf(direction: 'Unicorn-Killer', tags: {app_instance: 0}, values: {kill: 1})
11
7
  end
12
8
  end
13
- end
14
-
15
- if defined?(Unicorn::HttpServer) && defined?(Prometheus)
16
- module HttpServerExtensions
17
- def kill_worker(signal, wpid)
18
- Prometheus::UNICORN_KILLS.increment
19
- super
20
- end
21
- end
22
-
23
- module WorkerExtensions
24
- def soft_kill(sig)
25
- Prometheus::UNICORN_KILLS.increment
26
- super
27
- end
28
- end
29
-
30
- class Unicorn::HttpServer
31
- prepend HttpServerExtensions
32
- end
33
-
34
- class Unicorn::Worker
35
- prepend WorkerExtensions
36
- end
37
9
  end
@@ -3,11 +3,6 @@ ZuoraConnect::Engine.routes.draw do
3
3
  get '/internal/data' => 'static#metrics'
4
4
  post '/initialize_app' => 'static#initialize_app'
5
5
 
6
- if ENV['PROVISION_USER'].present? && ENV['PROVISION_SECRET'].present?
7
- post '/provision' => 'static#provision'
8
- get '/instance/:id/user' => 'static#instance_user'
9
- end
10
-
11
6
  namespace :api do
12
7
  namespace :v1 do
13
8
  resources :app_instance, :only => [:index], defaults: {format: :json} do
@@ -7,7 +7,7 @@ module ZuoraConnect
7
7
  def call(env)
8
8
  begin
9
9
  @app.call(env)
10
- rescue DynamicRailsError => error
10
+ rescue ActionDispatch::ParamsParser::ParseError => error
11
11
  if env['HTTP_ACCEPT'] =~ /application\/json/ || env['CONTENT_TYPE'] =~ /application\/json/
12
12
  return [
13
13
  400, { "Content-Type" => "application/json" },
@@ -18,16 +18,5 @@ module ZuoraConnect
18
18
  end
19
19
  end
20
20
  end
21
-
22
- # Note(hartley): remove once the minimum supported version of Rails is 5.2
23
- class DynamicRailsError < StandardError
24
- def self.===(exception)
25
- if Rails.version >= "5.2"
26
- exception.is_a?(ActionDispatch::Http::Parameters::ParseError)
27
- else
28
- exception.is_a?(ActionDispatch::ParamsParser::ParseError)
29
- end
30
- end
31
- end
32
21
  end
33
- end
22
+ end
@@ -64,22 +64,6 @@ module ZuoraConnect
64
64
  #Remove bad headers
65
65
  @bad_headers.each { |header| env.delete(header) }
66
66
 
67
- if defined?(Prometheus) && env['PATH_INFO'] == '/connect/internal/metrics'
68
- # Prometheus Stuff
69
- metrics = ZuoraConnect::AppInstance.get_metrics('stats')
70
- redis_up = metrics.present? && metrics.dig(:Resque, :Workers_Total).present? ? 1 : 0
71
- Prometheus::REDIS_CONNECTION.set(redis_up)
72
-
73
- process_prometheus_metric(metrics: metrics)
74
-
75
- if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
76
- ZuoraConnect::AppInstanceBase.unicorn_listener_stats.each do |key, value|
77
- gauge = Prometheus.const_get("unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_').upcase)
78
- gauge.set(value) if gauge.present?
79
- end
80
- end
81
- end
82
-
83
67
  #Thread.current[:appinstance] = nil
84
68
  start_time = Time.now
85
69
  begin
@@ -93,6 +77,35 @@ module ZuoraConnect
93
77
  ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: 'request-inbound-assets', tags: tags, values: values)
94
78
  end
95
79
 
80
+ if defined? Prometheus
81
+ #Prometheus Stuff
82
+ if env['PATH_INFO'] == '/connect/internal/metrics'
83
+
84
+ #Do something before each scrape
85
+ if defined? Resque.redis
86
+ begin
87
+
88
+ Resque.redis.ping
89
+
90
+ Prometheus::REDIS_CONNECTION.set({connection:'redis',name: ZuoraConnect::Telegraf.app_name},1)
91
+ Prometheus::FINISHED_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:processed])
92
+ Prometheus::PENDING_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:pending])
93
+ Prometheus::ACTIVE_WORKERS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:working])
94
+ Prometheus::WORKERS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:workers])
95
+ Prometheus::FAILED_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:failed])
96
+
97
+ rescue Redis::CannotConnectError
98
+ Prometheus::REDIS_CONNECTION.set({connection:'redis',name: ZuoraConnect::Telegraf.app_name},0)
99
+ end
100
+
101
+ if ZuoraConnect.configuration.custom_prometheus_update_block != nil
102
+ ZuoraConnect.configuration.custom_prometheus_update_block.call()
103
+ end
104
+ end
105
+
106
+ end
107
+ end
108
+
96
109
  # Uncomment following block of code for handling engine requests/requests without controller
97
110
  # else
98
111
  # # Handling requests which do not have controllers (engines)
@@ -106,10 +119,10 @@ module ZuoraConnect
106
119
  content_type = @headers['Content-Type'].split(';')[0] if @headers['Content-Type']
107
120
  content_type = content_type.gsub('text/javascript', 'application/javascript')
108
121
  tags = {status: @status, content_type: content_type}
109
-
122
+
110
123
  tags = tags.merge({controller: 'ActionController'})
111
124
  tags = tags.merge({action: 'RoutingError' }) if @status == 404
112
-
125
+
113
126
  values = {response_time: ((Time.now - start_time)*1000).round(2) }
114
127
 
115
128
  ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: :inbound, tags: tags, values: values)
@@ -120,32 +133,5 @@ module ZuoraConnect
120
133
  [@status, @headers, @response]
121
134
  end
122
135
  end
123
-
124
- def process_prometheus_metric(type: 'none', metrics: {})
125
- return if metrics.blank?
126
-
127
- prometheus = Prometheus::Client.registry
128
- most_recent_aggregation = {}
129
- if Prometheus::Client.config.data_store.is_a?(Prometheus::Client::DataStores::DirectFileStore)
130
- most_recent_aggregation[:aggregation] = :most_recent
131
- end
132
- metrics.each do |key, value|
133
- next if %w[app_name url].include?(key.to_s)
134
-
135
- if value.is_a?(Hash)
136
- process_prometheus_metric(type: key.to_s, metrics: value)
137
- else
138
- gauge_name = key.to_s.downcase.gsub(/[^a-z0-9_]/, '_')
139
- gauge = prometheus.get(gauge_name.to_sym) || prometheus.gauge(
140
- gauge_name.to_sym,
141
- docstring: "#{key} metric",
142
- labels: %i(type name),
143
- preset_labels: { type: type, name: ZuoraConnect::Telegraf.app_name },
144
- store_settings: most_recent_aggregation
145
- )
146
- gauge.set(value)
147
- end
148
- end
149
- end
150
136
  end
151
137
  end
@@ -92,7 +92,7 @@ module Resque
92
92
  log_with_severity :error, "Error reserving job: #{ex.inspect}"
93
93
  log_with_severity :error, ex.backtrace.join("\n")
94
94
  end
95
- raise ex
95
+ raise e
96
96
  end
97
97
 
98
98
  def create_job(queue, payload)
@@ -12,14 +12,14 @@ module Resque
12
12
  when "Hash"
13
13
  data = args.merge({:worker_class => self.to_s})
14
14
  end
15
- if Rails.logger.is_a?(Ougai::Logger)
15
+ if Rails.logger.is_a?(Ougai::Logger)
16
16
  Rails.logger.with_fields = {job: data, trace_id: SecureRandom.uuid, name: "RailsWorker"}
17
17
  end
18
18
 
19
19
  begin
20
- connection_count ||= 0
20
+ connection_count ||= 0
21
21
  @appinstance = ZuoraConnect::AppInstance.find(args['app_instance_id'].to_i)
22
- Rails.logger.info('Starting job')
22
+ job_start_log(args)
23
23
 
24
24
  @appinstance.new_session(holding_pattern: true)
25
25
  rescue ActiveRecord::RecordNotFound => exception
@@ -52,12 +52,12 @@ module Resque
52
52
  return
53
53
  rescue ZuoraConnect::Exceptions::ConnectCommunicationError => exception
54
54
  Rails.logger.warn("Enqueue Job Again ~ 2 mins", exception)
55
- @appinstance.queue_pause(time: 2.minutes.to_i)
55
+ @appinstance.queue_pause(time: 2.minutes.to_i)
56
56
  Resque.enqueue_to(self.job.queue, self.job.payload['class'], args)
57
57
  return
58
58
  rescue Net::ReadTimeout, Net::OpenTimeout, Errno::ECONNRESET, Errno::ECONNREFUSED, SocketError => exception
59
59
  Rails.logger.warn("Enqueue Job Again ~ 2 mins", exception)
60
- @appinstance.queue_pause(time: 2.minutes.to_i)
60
+ @appinstance.queue_pause(time: 2.minutes.to_i)
61
61
  Resque.enqueue_to(self.job.queue, self.job.payload['class'], args)
62
62
  return
63
63
  end
@@ -68,6 +68,10 @@ module Resque
68
68
  @appinstance.cache_app_instance if defined?(@appinstance)
69
69
  Rails.logger.flush if Rails.logger.methods.include?(:flush)
70
70
  end
71
+
72
+ def job_start_log(args)
73
+ Rails.logger.info("Starting job")
74
+ end
71
75
  end
72
76
  end
73
- end
77
+ end
@@ -13,9 +13,6 @@ require 'logging/connect_formatter'
13
13
  require 'metrics/influx/point_value'
14
14
  require 'metrics/net'
15
15
  require 'mono_logger'
16
- require 'zuora_connect/zuora_audit'
17
- require 'active_record'
18
- ::ActiveRecord::Base.send :include, ZuoraConnect::ZuoraAudit
19
16
 
20
17
  module ZuoraConnect
21
18
  class << self
@@ -124,24 +124,14 @@ module ZuoraConnect
124
124
  ElasticAPM.set_user(session["#{@appinstance.id}::user::email"]) if defined?(ElasticAPM) && ElasticAPM.running?
125
125
  PaperTrail.whodunnit = session["#{@appinstance.id}::user::email"] if defined?(PaperTrail)
126
126
  end
127
-
128
- locale = (session["#{@appinstance.id}::user::locale"] || "").gsub("_", "-")
129
127
  begin
128
+ locale = session["#{@appinstance.id}::user::locale"]
130
129
  I18n.locale = locale.present? ? locale : @appinstance.locale
131
130
  rescue I18n::InvalidLocale => ex
132
- if locale.include?("-")
133
- locale = locale.split("-").first
134
- retry
135
- elsif locale != session["#{@appinstance.id}::user::language"]
136
- locale = session["#{@appinstance.id}::user::language"]
137
- retry
138
- end
139
131
  ZuoraConnect.logger.error(ex) if !ZuoraConnect::AppInstance::IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
140
132
  end
141
133
  begin
142
- if @appinstance.user_timezone.blank?
143
- Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
144
- end
134
+ Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
145
135
  rescue
146
136
  ZuoraConnect.logger.error(ex)
147
137
  end
@@ -229,80 +219,6 @@ module ZuoraConnect
229
219
  return (request.headers['ZuoraCurrentEntity'].present? || cookies['ZuoraCurrentEntity'].present?)
230
220
  end
231
221
 
232
- def create_new_instance
233
- ZuoraConnect::AppInstance.read_master_db do
234
- Thread.current[:appinstance] = nil
235
- ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
236
- Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
237
-
238
- if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
239
- ElasticAPM.set_label(:trace_id, request.uuid)
240
- end
241
-
242
- zuora_host = request.headers['zuora-host']
243
- zuora_entity_id = (request.headers['zuora-entity-ids'] || '').gsub(
244
- '-',
245
- ''
246
- ).split(',').first
247
-
248
- # Validate host present
249
- if zuora_host.blank?
250
- render json: {
251
- status: 401,
252
- message: 'zuora-host header was not supplied.'
253
- }, status: :unauthorized
254
- return
255
- end
256
-
257
- # Validate entity-ids present
258
- if zuora_entity_id.blank?
259
- render json: {
260
- status: 401,
261
- message: 'zuora-entity-ids header was not supplied.'
262
- }, status: :unauthorized
263
- return
264
- end
265
-
266
- rest_domain = ZuoraAPI::Login.new(url: "https://#{zuora_host}").rest_domain
267
- app_instance_id = ZuoraConnect::AppInstance.where(
268
- 'zuora_entity_ids ?& array[:entities] AND zuora_domain = :host',
269
- entities: [zuora_entity_id],
270
- host: rest_domain
271
- ).pluck(:id).first
272
-
273
- if app_instance_id.present?
274
- render json: {
275
- status: 409,
276
- message: 'Instance already exists.',
277
- app_instance_id: app_instance_id
278
- }, status: 409
279
- else
280
- Apartment::Tenant.switch!("public")
281
- retry_count = 3
282
- begin
283
- @appinstance = new_instance(
284
- next_instance_id,
285
- zuora_entity_id,
286
- rest_domain,
287
- retry_count: retry_count
288
- )
289
- rescue ActiveRecord::RecordNotUnique
290
- retry if (retry_count -= 1).positive?
291
- return
292
- end
293
-
294
- app_instance_id = @appinstance.id
295
- end
296
-
297
- begin
298
- Apartment::Tenant.switch!('public')
299
- Apartment::Tenant.create(app_instance_id.to_s)
300
- rescue Apartment::TenantExists
301
- ZuoraConnect.logger.debug('Tenant Already Exists')
302
- end
303
- end
304
- end
305
-
306
222
  private
307
223
  def setup_instance_via_prod_mode
308
224
  zuora_entity_id = request.headers['ZuoraCurrentEntity'] || cookies['ZuoraCurrentEntity']
@@ -310,7 +226,7 @@ module ZuoraConnect
310
226
  if zuora_entity_id.present?
311
227
  zuora_tenant_id = cookies['Zuora-Tenant-Id']
312
228
  zuora_user_id = cookies['Zuora-User-Id']
313
- zuora_host = request.headers['HTTP_X_FORWARDED_HOST'] || request.headers['Zuora-Host'] || 'apisandbox.zuora.com'
229
+ zuora_host = request.headers["HTTP_X_FORWARDED_HOST"] || "apisandbox.zuora.com"
314
230
 
315
231
  zuora_details = {'host' => zuora_host, 'user_id' => zuora_user_id, 'tenant_id' => zuora_tenant_id, 'entity_id' => zuora_entity_id}
316
232
  auth_headers = {}
@@ -412,16 +328,13 @@ module ZuoraConnect
412
328
 
413
329
  zuora_user_id = cookies['Zuora-User-Id'] || session["ZuoraCurrentIdentity"]['userId']
414
330
 
331
+ #One deployed instance
415
332
  if appinstances.size == 1
416
333
  ZuoraConnect.logger.debug("Instance is #{appinstances.to_h.keys.first}")
417
334
  @appinstance = ZuoraConnect::AppInstance.find(appinstances.to_h.keys.first)
418
- end
419
335
 
420
- # One deployed instance with credentials
421
- if defined?(@appinstance) && !@appinstance['zuora_logins'].nil?
422
336
  #Add user/update
423
337
  begin
424
- ZuoraConnect::ZuoraUser.reset_table_name
425
338
  @zuora_user = ZuoraConnect::ZuoraUser.where(:zuora_user_id => zuora_user_id).first
426
339
  rescue ActiveRecord::StatementInvalid => ex
427
340
  if ex.message.include?("PG::UndefinedTable") && ex.message.include?("zuora_users")
@@ -442,12 +355,10 @@ module ZuoraConnect
442
355
  @zuora_user = ZuoraConnect::ZuoraUser.create!(:zuora_user_id => zuora_user_id, :zuora_identity_response => {zuora_entity_id => session["ZuoraCurrentIdentity"]})
443
356
  end
444
357
  @zuora_user.session = session
445
- ZuoraConnect::ZuoraUser.current_user_id = zuora_user_id
446
358
  session["#{@appinstance.id}::user::localUserId"] = @zuora_user.id
447
359
  session["#{@appinstance.id}::user::email"] = session['ZuoraCurrentIdentity']["username"]
448
360
  session["#{@appinstance.id}::user::timezone"] = session['ZuoraCurrentIdentity']["timeZone"]
449
- session["#{@appinstance.id}::user::language"] = session['ZuoraCurrentIdentity']["language"]
450
- session["#{@appinstance.id}::user::locale"] = session['ZuoraCurrentIdentity']["locale"]
361
+ session["#{@appinstance.id}::user::locale"] = session['ZuoraCurrentIdentity']["language"]
451
362
  session["appInstance"] = @appinstance.id
452
363
 
453
364
  #We have multiple, user must pick
@@ -469,85 +380,79 @@ module ZuoraConnect
469
380
  return
470
381
  end
471
382
  Apartment::Tenant.switch!("public")
472
- retry_count = 3
473
- task_data = {}
474
- begin
475
- ActiveRecord::Base.transaction do
476
- ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
383
+ ActiveRecord::Base.transaction do
384
+ ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
385
+ appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host", entities: [zuora_entity_id], host: zuora_client.rest_domain).pluck(:id, :name)
477
386
 
478
- unless defined?(@appinstance)
479
- appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host", entities: [zuora_entity_id], host: zuora_client.rest_domain).pluck(:id, :name)
480
-
481
- if appinstances.size > 0
482
- redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
483
- return
484
- end
485
- end
387
+ if appinstances.size > 0
388
+ redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
389
+ return
390
+ end
486
391
 
487
- next_id = defined?(@appinstance) ? @appinstance.id : next_instance_id
488
- if task_data.blank?
489
- user = (ENV['DEIS_APP'] || "Application").split('-').map(&:capitalize).join(' ')
490
- body = {
491
- 'userId' => zuora_user_id,
492
- 'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
493
- 'customAuthorities' => [],
494
- 'additionalInformation' => {
495
- 'description' => "This user is for #{user} application.",
496
- 'name' => "#{user} API User #{next_id}"
497
- }
498
- }
499
-
500
- oauth_response, response = zuora_client.rest_call(
501
- method: :post,
502
- body: body.to_json,
503
- url: zuora_client.rest_endpoint("genesis/clients").gsub('v1/', ''),
504
- session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
505
- headers: auth_headers
506
- )
507
-
508
- new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
509
- if session["ZuoraCurrentUserInfo"].blank?
510
- client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
511
- else
512
- client_describe = session["ZuoraCurrentUserInfo"]
513
- end
392
+ next_id = (ZuoraConnect::AppInstance.all.where('id > 24999999').order(id: :desc).limit(1).pluck(:id).first || 24999999) + 1
393
+ user = (ENV['DEIS_APP'] || "Application").split('-').map(&:capitalize).join(' ')
394
+ body = {
395
+ 'userId' => zuora_user_id,
396
+ 'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
397
+ 'customAuthorities' => [],
398
+ 'additionalInformation' => {
399
+ 'description' => "This user is for #{user} application.",
400
+ 'name' => "#{user} API User #{next_id}"
401
+ }
402
+ }
403
+
404
+ oauth_response, response = zuora_client.rest_call(
405
+ method: :post,
406
+ body: body.to_json,
407
+ url: zuora_client.rest_endpoint("genesis/clients").gsub('v1/', ''),
408
+ session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
409
+ headers: auth_headers
410
+ )
514
411
 
515
- available_entities = client_describe["accessibleEntities"].select {|entity| entity['id'] == zuora_entity_id}
516
- task_data = {
517
- "id": next_id,
518
- "name": client_describe["tenantName"],
519
- "mode": "Collections",
520
- "status": "Running",
521
- ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
522
- "tenant_type": "Zuora",
523
- "username": session["ZuoraCurrentIdentity"]["username"],
524
- "url": new_zuora_client.url,
525
- "status": "Active",
526
- "oauth_client_id": oauth_response['clientId'],
527
- "oauth_secret": oauth_response['clientSecret'],
528
- "authentication_type": "OAUTH",
529
- "entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
530
- },
531
- "tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
532
- }
533
- end
412
+ new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
413
+ if session["ZuoraCurrentUserInfo"].blank?
414
+ client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
415
+ else
416
+ client_describe = session["ZuoraCurrentUserInfo"]
417
+ end
534
418
 
535
- if defined?(@appinstance)
536
- @appinstance.zuora_logins = task_data
537
- @appinstance.save(:validate => false)
419
+ available_entities = client_describe["accessibleEntities"].select {|entity| entity['id'] == zuora_entity_id}
420
+ task_data = {
421
+ "id": next_id,
422
+ "name": client_describe["tenantName"],
423
+ "mode": "Collections",
424
+ "status": "Running",
425
+ ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
426
+ "tenant_type": "Zuora",
427
+ "username": session["ZuoraCurrentIdentity"]["username"],
428
+ "url": new_zuora_client.url,
429
+ "status": "Active",
430
+ "oauth_client_id": oauth_response['clientId'],
431
+ "oauth_secret": oauth_response['clientSecret'],
432
+ "authentication_type": "OAUTH",
433
+ "entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
434
+ },
435
+ "tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
436
+ }
437
+ mapped_values = {:id => next_id, :api_token => rand(36**64).to_s(36), :token => rand(36**64).to_s(36), :zuora_logins => task_data, :oauth_expires_at => Time.now + 1000.years, :zuora_domain => zuora_client.rest_domain, :zuora_entity_ids => [zuora_entity_id]}
438
+ @appinstance = ZuoraConnect::AppInstance.new(mapped_values)
439
+ retry_count = 0
440
+ begin
441
+ @appinstance.save(:validate => false)
442
+ rescue ActiveRecord::RecordNotUnique => ex
443
+ if (retry_count += 1) < 3
444
+ @appinstance.assign_attributes({:api_token => rand(36**64).to_s(36), :token => rand(36**64).to_s(36)})
445
+ retry
538
446
  else
539
- @appinstance = new_instance(
540
- next_id,
541
- zuora_entity_id,
542
- zuora_client.rest_domain,
543
- task_data: task_data,
544
- retry_count: retry_count
545
- )
447
+ Thread.current[:appinstance] = nil
448
+ session["appInstance"] = nil
449
+ render "zuora_connect/static/error_handled", :locals => {
450
+ :title => "Application could not create unique tokens.",
451
+ :message => "Please contact support or retry launching application."
452
+ }, :layout => false
453
+ return
546
454
  end
547
455
  end
548
- rescue ActiveRecord::RecordNotUnique
549
- retry if (retry_count -= 1).positive?
550
- return
551
456
  end
552
457
 
553
458
  Apartment::Tenant.switch!("public")
@@ -578,8 +483,8 @@ module ZuoraConnect
578
483
 
579
484
  rescue ZuoraAPI::Exceptions::ZuoraAPIError, Exception => ex
580
485
  if ex.message.include?("Referenced User resource(s) not found") && ex.class == ZuoraAPI::Exceptions::ZuoraAPIError
581
- locals = {title: "Provisioning Error", message: "New tenants need to be provisioned by API Gateway('#{ex.message}'). Please contact support."}
582
- render "zuora_connect/static/error_handled", locals: locals, status: 200, layout: false
486
+ locals = {title: "Provisioning Error", message: "New tenats need to be provisioned by API Gateway('#{ex.message}'). Please contact support."}
487
+ render "zuora_connect/static/error_handled", locals: locals, status: 400, layout: false
583
488
  else
584
489
  session.clear
585
490
  if defined?(ex.response) && ex.response.present? && defined?(ex.response.body)
@@ -635,57 +540,12 @@ module ZuoraConnect
635
540
  end
636
541
  end
637
542
 
638
- def next_instance_id
639
- min_instance_id = 24_999_999
640
- (ZuoraConnect::AppInstance.all.where("id > #{min_instance_id}").order(id: :desc).limit(1).pluck(:id).first || min_instance_id) + 1
641
- end
642
-
643
- def new_instance(id, zuora_entity_id, rest_domain, task_data: nil, retry_count: 0)
644
- app_instance = ZuoraConnect::AppInstance.new(
645
- :id => id,
646
- :api_token => generate_token,
647
- :token => generate_token,
648
- :oauth_expires_at => Time.now + 1000.years,
649
- :zuora_domain => rest_domain,
650
- :zuora_entity_ids => [zuora_entity_id]
651
- )
652
-
653
- if task_data.nil?
654
- # no encryption
655
- app_instance['zuora_logins'] = task_data
656
- else
657
- # kms encrypt
658
- app_instance.zuora_logins = task_data
659
- end
660
-
661
- begin
662
- app_instance.save(:validate => false)
663
- rescue ActiveRecord::RecordNotUnique
664
- raise if retry_count > 1
665
-
666
- Thread.current[:appinstance] = nil
667
- session['appInstance'] = nil
668
- render 'zuora_connect/static/error_handled', :locals => {
669
- :title => 'Application could not create unique tokens.',
670
- :message => 'Please contact support or retry launching application.'
671
- }, :layout => false
672
- return
673
- end
674
-
675
- app_instance
676
- end
677
-
678
- def generate_token
679
- rand(36**64).to_s(36)
680
- end
681
-
682
543
  def setup_instance_via_dev_mode
683
544
  session["appInstance"] = ZuoraConnect.configuration.dev_mode_appinstance
684
545
  user = ZuoraConnect.configuration.dev_mode_user
685
546
  key = ZuoraConnect.configuration.dev_mode_pass
686
547
  values = {:user => user , :key => key, :appinstance => session["appInstance"]}
687
548
  @appinstance = ZuoraConnect::AppInstance.find_by(:id => values[:appinstance].to_i)
688
- ZuoraConnect::ZuoraUser.current_user_id = 0
689
549
  if @appinstance.blank?
690
550
  Apartment::Tenant.switch!("public")
691
551
  begin