zuora_connect 2.0.57 → 2.0.58a

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: ae04188bc84b9fd594f1a2453128a9f7f8d489e9edd9ffd053ef51c09c32b02d
4
- data.tar.gz: 3f19d9ed178c02807f44dbed319f5d2c5b47301de9bdc6666ce5df320cc8c40c
3
+ metadata.gz: 4a03cd7450b81983c6d782fe911babc655153094bf6ff41fec0b3ed3a3a06888
4
+ data.tar.gz: 99eff46c23e53cd0d09b4c0fdafe199c239f800ca55dcaed255674d69729a2db
5
5
  SHA512:
6
- metadata.gz: 9a1249ce65d708fe4bd792c890b49946ce1dea1c1ffba97a98ef397d98e69014e5f24021b700f0b2c980c2ce2292b601fbbb9550110f7e66b4099908ee0467ac
7
- data.tar.gz: d40bdadd5ccbe7e2416f3ab354830f05aadec4c1c5faea71dccf8a87f1df0e012bfe4a49f1ed7f0a6e29c97ac4e3c04d8548ba48094f81d01f30c55c4484753b
6
+ metadata.gz: 7cd29354de9ecb38d51ce8361029fc6a15a008f76d659723245fe12686068757fa34b768198a571ed4390bed750e49086b49fb1099702c2475b66b4506e49c57
7
+ data.tar.gz: beb5f965e6f8a88bbec73ecb507d595f82f468e419a958aec6dc33a8d4d17f17ccbf45fb90669dbf252d8e92799b9a7778323a833a618dd87a966dbf25fac51d
@@ -4,12 +4,31 @@ window.define = previousDefine;
4
4
  if (isHallway()) {
5
5
  $( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
6
6
  if ( jqxhr.status === 401) {
7
- window.location.href = '/apps/newlogin.do?retURL=' + window.location.pathname;
7
+ fetch("https://" + window.location.host + "/apps/v1/navigation").then(response => {
8
+ if (response.status === 401) {
9
+ deleteAllCookies();
10
+ window.location.href = '/apps/newlogin.do?retURL=' + window.location.pathname;
11
+ }
12
+ });
8
13
  }
9
14
  });
10
15
  }
11
16
 
12
17
  function isHallway() {
13
- var regex = new RegExp("^/services/");
14
- return window.location.pathname.match(regex);
18
+ var regex = new RegExp("(?<=\\/)services\\/.*");
19
+ if (regex.test(window.location.pathname)) {
20
+ return window.location.pathname.match(regex)[0]
21
+ }
22
+ return null;
23
+ }
24
+
25
+ function deleteAllCookies() {
26
+ var cookies = document.cookie.split(";");
27
+
28
+ for (var i = 0; i < cookies.length; i++) {
29
+ var cookie = cookies[i];
30
+ var eqPos = cookie.indexOf("=");
31
+ var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
32
+ document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";
33
+ }
15
34
  }
@@ -1,10 +1,11 @@
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]
3
+ before_action :authenticate_connect_app_request, :except => [:metrics, :health, :initialize_app, :provision]
4
+ before_action :clear_connect_app_session, :only => [:metrics, :health, :initialize_app, :provision]
5
+ after_action :persist_connect_app_session, :except => [:metrics, :health, :initialize_app, :provision]
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]
8
9
 
9
10
  def metrics
10
11
  type = params[:type].present? ? params[:type] : "versions"
@@ -34,11 +35,13 @@ module ZuoraConnect
34
35
  def initialize_app
35
36
  begin
36
37
  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
38
+ unless performed?
39
+ @appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
40
+ render json: {
41
+ message: 'Success',
42
+ status: 200
43
+ }, status: 200
44
+ end
42
45
  rescue => ex
43
46
  Rails.logger.error("Failed to Initialize application", ex)
44
47
  if performed?
@@ -52,6 +55,28 @@ module ZuoraConnect
52
55
  end
53
56
  end
54
57
 
58
+ def provision
59
+ create_new_instance
60
+ unless performed?
61
+ render json: {
62
+ status: 200,
63
+ message: 'Success',
64
+ app_instance_id: @appinstance.id
65
+ }, status: 200
66
+ end
67
+ rescue StandardError => e
68
+ message = 'Failed to provision new instance'
69
+ if performed?
70
+ Rails.logger.error("#{message}: #{performed?}", e)
71
+ else
72
+ Rails.logger.error(message, e)
73
+ render json: {
74
+ status: 500,
75
+ message: message
76
+ }, status: 500
77
+ end
78
+ end
79
+
55
80
  private
56
81
 
57
82
  def clear_connect_app_session
@@ -20,7 +20,7 @@ module ZuoraConnect
20
20
  BLANK_OBJECT_ID_LOOKUP = 'BlankValueSupplied'
21
21
  HOLDING_PATTERN_SLEEP = 5.seconds
22
22
  CONNECT_APPLICATION_ID = 0
23
- CONNECT_COMMUNICATION_SLEEP= 5.seconds
23
+ CONNECT_COMMUNICATION_SLEEP = Rails.env.test? ? 0.seconds : 5.seconds
24
24
  IGNORED_LOCALS = ['fr', 'ja', 'es', 'zh', 'de']
25
25
  INTERNAL_HOSTS = []
26
26
  LOGIN_TENANT_DESTINATION = 'target_login'
@@ -98,7 +98,9 @@ module ZuoraConnect
98
98
  Redis.current.zrem("InstanceRefreshing", self.id)
99
99
  end
100
100
  if defined?(Resque.redis)
101
- Resque.redis.zrem("PauseQueue", self.id)
101
+ Resque.redis.zrange("PauseQueue", 0, -1).each do |key|
102
+ Resque.redis.zrem("PauseQueue", key) if key.split("__").first.to_i == self.id
103
+ end
102
104
  end
103
105
  return true
104
106
  end
@@ -161,6 +163,7 @@ module ZuoraConnect
161
163
  end
162
164
 
163
165
  self.build_task(task_data: mock_task_data, session: session)
166
+ self.last_refresh = Time.now.to_i
164
167
  else
165
168
  time_expire = (session["#{self.id}::last_refresh"] || Time.now).to_i - INSTANCE_REFRESH_WINDOW.ago.to_i
166
169
 
@@ -202,14 +205,14 @@ module ZuoraConnect
202
205
  else
203
206
  self.new_session_message = "REBUILDING - Expires in #{time_expire} seconds"
204
207
  end
205
- ZuoraConnect.logger.debug(self.new_session_message)
208
+ ZuoraConnect.logger.debug(self.new_session_message, self.default_ougai_items)
206
209
  self.build_task(task_data: session["#{self.id}::task_data"], session: session)
207
210
  end
208
211
  end
209
212
  return self
210
213
  rescue ZuoraConnect::Exceptions::HoldingPattern => ex
211
214
  while self.marked_for_refresh?
212
- ZuoraConnect.logger.info("Holding - Expires in #{self.reset_mark_expires_at}. '#{self.new_session_message}'")
215
+ ZuoraConnect.logger.info("Holding - Expires in #{self.reset_mark_expires_at}. '#{self.new_session_message}'", self.default_ougai_items)
213
216
  sleep(HOLDING_PATTERN_SLEEP)
214
217
  end
215
218
  self.reload_attributes([:refresh_token, :oauth_expires_at, :access_token])
@@ -218,17 +221,17 @@ module ZuoraConnect
218
221
  rescue ZuoraConnect::Exceptions::MissMatch => ex
219
222
  self.delete_app_instance
220
223
  session = {}
221
- ZuoraConnect.logger.error(ex, app_instance_id_new: self.task_data['id'])
224
+ ZuoraConnect.logger.error(ex, self.default_ougai_items.merge({app_instance_id_new: self.task_data['id']}))
222
225
  retry
223
226
  rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
224
227
  raise
225
228
  rescue => ex
226
229
  if recoverable_session
227
- ZuoraConnect.logger.warn("REBUILDING - Using backup expired cache", ex)
230
+ ZuoraConnect.logger.warn("REBUILDING - Using backup expired cache", ex, self.default_ougai_items)
228
231
  self.build_task(task_data: session["#{self.id}::task_data"], session: session)
229
232
  return self
230
233
  else
231
- ZuoraConnect.logger.error("Failed new session", ex)
234
+ ZuoraConnect.logger.error("Failed new session", ex, self.default_ougai_items)
232
235
  raise
233
236
  end
234
237
  ensure
@@ -276,11 +279,8 @@ module ZuoraConnect
276
279
  #Check how app was deployed
277
280
  if self.id < 25000000 && !skip_connect
278
281
  self.check_oauth_state
279
- start = Time.now
280
282
  response = HTTParty.get(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/tasks/#{self.id}.json",:body => {:access_token => self.access_token})
281
- response_time = Time.now - start
282
283
 
283
- ZuoraConnect.logger.debug("REFRESH TASK - Connect Task Info Request Time #{response_time.round(2).to_s}")
284
284
  if response.code == 200
285
285
  begin
286
286
  parsed_json = JSON.parse(response.body)
@@ -312,7 +312,7 @@ module ZuoraConnect
312
312
  refresh_count += 1
313
313
  if refresh_count < 3
314
314
  sleep(10)
315
- ZuoraConnect.logger.debug("REFRESH TASK - Connection Failure Retrying(#{refresh_count})", ex)
315
+ ZuoraConnect.logger.debug("REFRESH TASK - Connection Failure Retrying(#{refresh_count})", ex, self.default_ougai_items)
316
316
  retry
317
317
  else
318
318
  ZuoraConnect.logger.fatal("REFRESH TASK - Connection Failed", ex)
@@ -321,17 +321,17 @@ module ZuoraConnect
321
321
  rescue ZuoraConnect::Exceptions::ConnectCommunicationError => ex
322
322
  refresh_count += 1
323
323
  if refresh_count < 3
324
- ZuoraConnect.logger.debug("REFRESH TASK - Communication Failure Retrying(#{refresh_count})", ex)
324
+ ZuoraConnect.logger.debug("REFRESH TASK - Communication Failure Retrying(#{refresh_count})", ex, self.default_ougai_items)
325
325
  self.refresh_oauth if ex.code == 401
326
326
  retry
327
327
  else
328
- ZuoraConnect.logger.fatal("REFRESH TASK - Communication Failed #{ex.code}", ex)
328
+ ZuoraConnect.logger.fatal("REFRESH TASK - Communication Failed #{ex.code}", ex, self.default_ougai_items)
329
329
  raise
330
330
  end
331
331
  end
332
332
  rescue => ex
333
333
  if self['zuora_logins'].present?
334
- ZuoraConnect.logger.warn("REFRESH TASK - Fallback to local encrypted store", ex)
334
+ ZuoraConnect.logger.warn("REFRESH TASK - Fallback to local encrypted store", ex, self.default_ougai_items)
335
335
  skip_connect = true
336
336
  retry
337
337
  end
@@ -653,16 +653,12 @@ module ZuoraConnect
653
653
  end
654
654
 
655
655
  def refresh_oauth
656
- refresh_oauth_count ||= 0
657
- start = Time.now
658
- params = {
659
- :grant_type => "refresh_token",
660
- :redirect_uri => ZuoraConnect.configuration.oauth_client_redirect_uri,
661
- :refresh_token => self.refresh_token
662
- }
663
- response = HTTParty.post("#{ZuoraConnect.configuration.url}/oauth/token",:body => params)
664
- response_time = Time.now - start
665
- ZuoraConnect.logger.debug("REFRESH OAUTH - In #{response_time.round(2).to_s}")
656
+ refresh_oauth_count ||= 0
657
+ response = HTTParty.post("#{ZuoraConnect.configuration.url}/oauth/token", body: {
658
+ :grant_type => "refresh_token",
659
+ :redirect_uri => ZuoraConnect.configuration.oauth_client_redirect_uri,
660
+ :refresh_token => self.refresh_token
661
+ })
666
662
 
667
663
  if response.code == 200
668
664
  response_body = JSON.parse(response.body)
@@ -676,11 +672,11 @@ module ZuoraConnect
676
672
  end
677
673
  rescue *(ZuoraAPI::Login::CONNECTION_EXCEPTIONS + ZuoraAPI::Login::CONNECTION_READ_EXCEPTIONS) => ex
678
674
  if (refresh_oauth_count += 1) < 3
679
- sleep(5)
680
- ZuoraConnect.logger.debug("REFRESH OAUTH - Connection Failure Retrying(#{refresh_oauth_count})", ex)
675
+ sleep(CONNECT_COMMUNICATION_SLEEP)
676
+ ZuoraConnect.logger.debug("REFRESH OAUTH - Connection Failure Retrying(#{refresh_oauth_count})", ex, self.default_ougai_items)
681
677
  retry
682
678
  else
683
- ZuoraConnect.logger.fatal("REFRESH OAUTH - Connection Failed", ex)
679
+ Rails.logger.fatal("REFRESH OAUTH - Connection Failed", ex, self.default_ougai_items)
684
680
  raise
685
681
  end
686
682
  rescue ZuoraConnect::Exceptions::ConnectCommunicationError => ex
@@ -691,10 +687,10 @@ module ZuoraConnect
691
687
  return if !self.oauth_expired?
692
688
 
693
689
  if (refresh_oauth_count += 1) < 3
694
- ZuoraConnect.logger.debug("REFRESH OAUTH - Communication Failure Retrying(#{refresh_oauth_count})", ex)
690
+ ZuoraConnect.logger.debug("REFRESH OAUTH - Communication Failure Retrying(#{refresh_oauth_count})", ex, self.default_ougai_items)
695
691
  retry
696
692
  else
697
- ZuoraConnect.logger.fatal("REFRESH OAUTH - Communication Failed #{ex.code}", ex)
693
+ ZuoraConnect.logger.fatal("REFRESH OAUTH - Communication Failed #{ex.code}", ex, self.default_ougai_items)
698
694
  raise
699
695
  end
700
696
  end
@@ -744,10 +740,10 @@ module ZuoraConnect
744
740
  end
745
741
  end
746
742
  if cached_instance.blank?
747
- ZuoraConnect.logger.debug("Cached AppInstance Missing")
743
+ ZuoraConnect.logger.debug("Cached AppInstance Missing", self.default_ougai_items)
748
744
  return session
749
745
  else
750
- ZuoraConnect.logger.debug("Cached AppInstance Found")
746
+ ZuoraConnect.logger.debug("Cached AppInstance Found", self.default_ougai_items)
751
747
  return decrypt_data(data: cached_instance, rescue_return: session).merge(session)
752
748
  end
753
749
  else
@@ -763,7 +759,7 @@ module ZuoraConnect
763
759
  if defined?(Redis.current)
764
760
  #Task data must be present and the last refresh cannot be old. We dont want to overwite new cache data with old
765
761
  if self.task_data.present? && (self.last_refresh.to_i > INSTANCE_REFRESH_WINDOW.ago.to_i)
766
- ZuoraConnect.logger.debug("Caching AppInstance")
762
+ ZuoraConnect.logger.debug("Caching AppInstance", self.default_ougai_items)
767
763
  Redis.current.setex("AppInstance:#{self.id}", INSTANCE_REDIS_CACHE_PERIOD.to_i, self.encrypt_data(data: self.save_data))
768
764
  end
769
765
  end
@@ -827,10 +823,10 @@ module ZuoraConnect
827
823
  begin
828
824
  return JSON.parse(encryptor.decrypt_and_verify(CGI::unescape(data)))
829
825
  rescue ActiveSupport::MessageVerifier::InvalidSignature => ex
830
- ZuoraConnect.logger.error("Error Decrypting", ex) if log_fatal
826
+ ZuoraConnect.logger.error("Error Decrypting", ex, self.default_ougai_items) if log_fatal
831
827
  return rescue_return
832
828
  rescue JSON::ParserError => ex
833
- ZuoraConnect.logger.error("JSON Parse Error", ex) if log_fatal
829
+ ZuoraConnect.logger.error("JSON Parse Error", ex, self.default_ougai_items) if log_fatal
834
830
  return encryptor.decrypt_and_verify(CGI::unescape(data))
835
831
  end
836
832
  end
@@ -1127,6 +1123,15 @@ module ZuoraConnect
1127
1123
  # Data from each schema will be loaded into table(aggregate_name) into the public schema
1128
1124
  def self.refresh_aggregate_table(aggregate_name: 'all_tasks_processing', table_name: 'tasks', where_clause: "where status in ('Processing', 'Queued')", index_table: true, ignore_indexes: [])
1129
1125
  self.update_functions
1126
+
1127
+ sql_result = ActiveRecord::Base.connection.execute <<-eos
1128
+ SELECT pid, relname, mode
1129
+ FROM pg_locks l
1130
+ JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r'
1131
+ WHERE t.relname = '#{aggregate_name}' AND l.mode ='AccessExclusiveLock';
1132
+ eos
1133
+ raise ZuoraConnect::Exceptions::Error.new("An existing lock detected while dropping table '#{aggregate_name}'") if sql_result.count > 0
1134
+
1130
1135
  if index_table
1131
1136
  ActiveRecord::Base.connection.execute('SELECT "shared_extensions".refresh_aggregate_table(\'%s\', \'%s\', %s, \'Index\', \'{%s}\');' % [aggregate_name, table_name, ActiveRecord::Base.connection.quote(where_clause), ignore_indexes.map { |index| "\"#{index}\"" }.join(',')])
1132
1137
  else
@@ -1214,6 +1219,16 @@ module ZuoraConnect
1214
1219
  end
1215
1220
  end
1216
1221
 
1222
+ def self.without_sticking
1223
+ if self.connection.respond_to?(:without_sticking)
1224
+ self.connection.without_sticking do
1225
+ yield
1226
+ end
1227
+ else
1228
+ yield
1229
+ end
1230
+ end
1231
+
1217
1232
  method_hook :updateOption, :update_logins, :before => :check_oauth_state
1218
1233
  method_hook :new_session, :refresh, :build_task, :after => :apartment_switch
1219
1234
  end
@@ -3,12 +3,7 @@
3
3
  <title>Select Task ID</title>
4
4
  <meta name="viewport" content="width=device-width,initial-scale=1">
5
5
  <style>
6
- body {
7
- background-color: #EFEFEF;
8
- margin: 0;
9
- }
10
-
11
- div.connect-dialog {
6
+ .connect-dialog {
12
7
  width: 95%;
13
8
  max-width: 33em;
14
9
  margin: 4em auto 0;
@@ -16,7 +11,11 @@
16
11
  text-align: center;
17
12
  }
18
13
 
19
- div.connect-dialog > div {
14
+ .connect-dialog div {
15
+ background-color: white;
16
+ color: #2E2F30;
17
+ text-align: center;
18
+ font-family: arial, sans-serif;
20
19
  margin: 0 0 1em;
21
20
  border: 1px solid #CCC;
22
21
  border-right-color: #999;
@@ -27,19 +26,17 @@
27
26
  border-top-right-radius: 9px;
28
27
  border-bottom-left-radius: 9px;
29
28
  border-bottom-right-radius: 9px;
30
- background-color: white;
31
29
  padding: 7px 12% 0;
32
30
  box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
33
31
  }
34
32
 
35
- div.connect-dialog > h1 {
33
+ .connect-dialog h1 {
36
34
  font-size: 100%;
37
35
  color: #3D4B5A;
38
36
  line-height: 1.5em;
39
37
  }
40
38
 
41
-
42
- div.connect-dialog > div.launch_button {
39
+ .connect-dialog .launch_button {
43
40
  margin: 1em 0 1em;
44
41
  margin-right: auto;
45
42
  margin-left: auto;
@@ -3,6 +3,10 @@ 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
+ end
9
+
6
10
  namespace :api do
7
11
  namespace :v1 do
8
12
  resources :app_instance, :only => [:index], defaults: {format: :json} do
@@ -24,9 +24,13 @@ module Resque
24
24
  @appinstance.new_session(holding_pattern: true)
25
25
  rescue ActiveRecord::RecordNotFound => exception
26
26
  # If we can't find app_instance let make sure we cleanup
27
- Rails.logger.info("No instance found, purge")
28
- ZuoraConnect::AppInstance.new(id: args['app_instance_id'].to_i).prune_data
29
- return
27
+ if Redis.current.zscore("AppInstance:Deleted", args['app_instance_id'].to_i).present?
28
+ Rails.logger.info("No instance found, purge")
29
+ ZuoraConnect::AppInstance.new(id: args['app_instance_id'].to_i).prune_data
30
+ return
31
+ else
32
+ raise
33
+ end
30
34
  rescue ActiveRecord::StatementInvalid => exception
31
35
  if (connection_count += 1) <= 3 &&
32
36
  (
@@ -23,6 +23,8 @@ module ZuoraConnect
23
23
  case Rails.env.to_s
24
24
  when 'development'
25
25
  Rails.logger
26
+ when 'test'
27
+ Rails.logger
26
28
  else
27
29
  @logger ||= custom_logger(name: "Connect", level: Rails.logger.level)
28
30
  end
@@ -7,7 +7,7 @@ module ZuoraConnect
7
7
 
8
8
  attr_accessor :oauth_client_id, :oauth_client_secret, :oauth_client_redirect_uri
9
9
 
10
- attr_accessor :dev_mode_logins, :dev_mode_options, :dev_mode_mode, :dev_mode_appinstance, :dev_mode_user, :dev_mode_pass, :dev_mode_admin, :dev_mode_secret_access_key,:dev_mode_access_key_id,:aws_region, :s3_bucket_name, :s3_folder_name, :json_logging
10
+ attr_accessor :dev_mode_logins, :dev_mode_options, :dev_mode_mode, :dev_mode_appinstance, :dev_mode_user, :dev_mode_pass, :dev_mode_admin, :dev_mode_secret_access_key,:dev_mode_access_key_id,:aws_region, :s3_bucket_name, :s3_folder_name, :json_logging, :insert_migrations
11
11
 
12
12
  def initialize
13
13
  @default_locale = :en
@@ -19,6 +19,7 @@ module ZuoraConnect
19
19
  @additional_apartment_models = []
20
20
  @silencer_resque_finish = true
21
21
  @blpop_queue = false
22
+ @insert_migrations = true
22
23
 
23
24
  # Setting the app name for telegraf write
24
25
  @enable_metrics = false
@@ -42,7 +43,7 @@ module ZuoraConnect
42
43
  @aws_region = "us-west-2"
43
44
  @s3_bucket_name = "rbm-apps"
44
45
  @s3_folder_name = Rails.application.class.parent_name
45
- @json_logging = Rails.env.to_s == 'development' ? false : true
46
+ @json_logging = Rails.env.development? || Rails.env.test? ? false : true
46
47
  end
47
48
 
48
49
  def private_key
@@ -19,7 +19,6 @@ module ZuoraConnect
19
19
  ElasticAPM.set_label(:trace_id, request.uuid) if defined?(ElasticAPM) && ElasticAPM.running?
20
20
  end
21
21
  end
22
- start_time = Time.now
23
22
  if request.headers["API-Token"].present?
24
23
  @appinstance = ZuoraConnect::AppInstance.find_by(:api_token => request.headers["API-Token"])
25
24
  ZuoraConnect.logger.debug("API REQUEST - API token") if @appinstance.present?
@@ -48,7 +47,7 @@ module ZuoraConnect
48
47
  render json: {"status": 401, "message": "Missing mapping or no deployment for '#{zuora_host}-#{zuora_entity_id}' ."}, status: :unauthorized
49
48
  return
50
49
  elsif appinstances.size > 1
51
- render json: {"status": 401, "message": "More than one app instance binded to host and entity ids. Please indicate correct instance via 'zuora-instance-id' header"}, status: :unauthorized
50
+ render json: {"status": 401, "message": "More than one app instance binded to host and entity ids. Please indicate correct instance via 'zuora-instance-id' header", "instances": appinstances.map {|instance| instance.id }.sort }, status: :unauthorized
52
51
  return
53
52
  else
54
53
  @appinstance = appinstances.first
@@ -65,10 +64,6 @@ module ZuoraConnect
65
64
  else
66
65
  check_instance
67
66
  end
68
-
69
- if @appinstance.present?
70
- ZuoraConnect.logger.debug("Authenticate App API Request Completed In - #{(Time.now - start_time).round(2)}s")
71
- end
72
67
  end
73
68
  end
74
69
 
@@ -101,7 +96,6 @@ module ZuoraConnect
101
96
  ElasticAPM.set_label(:trace_id, request.uuid)
102
97
  end
103
98
  end
104
- start_time = Time.now
105
99
 
106
100
  if ZuoraConnect.configuration.mode == "Production"
107
101
  setup_instance_via_prod_mode
@@ -141,32 +135,30 @@ module ZuoraConnect
141
135
  rescue
142
136
  ZuoraConnect.logger.error(ex)
143
137
  end
144
-
145
- ZuoraConnect.logger.debug("Authenticate App Request Completed In - #{(Time.now - start_time).round(2)}s")
146
138
  end
147
139
  rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
148
140
  id = @appinstance.id
149
141
  ZuoraConnect::AppInstance.destroy(id)
150
142
  Apartment::Tenant.drop(id)
151
143
  render "zuora_connect/static/error_handled", :locals => {
152
- :title => "Application Setup Error",
144
+ :title => "Application Setup Error",
153
145
  :message => "Application cannot be run using Zuora Session. Delete old application \
154
146
  deployment and create new with Zuora Basic or OAuth credentials."
155
147
  }, :layout => false
156
- return
148
+ return
157
149
  rescue ZuoraConnect::Exceptions::AccessDenied => ex
158
150
  respond_to do |format|
159
- format.html {
151
+ format.html {
160
152
  render "zuora_connect/static/error_handled", :locals => {
161
- :title => "Application State Error",
153
+ :title => "Application State Error",
162
154
  :message => ex.message
163
- }, status: 401, layout: false
155
+ }, status: 401, layout: false
164
156
  }
165
- format.js {
157
+ format.js {
166
158
  render "zuora_connect/static/error_handled", :locals => {
167
- :title => "Application State Error",
159
+ :title => "Application State Error",
168
160
  :message => ex.message
169
- }, status: 401, layout: false
161
+ }, status: 401, layout: false
170
162
  }
171
163
  format.json { render json: {'errors' => ex.message}, status: 401 }
172
164
  format.all { render json: ex.message, status: 401 }
@@ -196,17 +188,17 @@ module ZuoraConnect
196
188
  raise ZuoraConnect::Exceptions::AccessDenied.new("User is not an authorized admin for this application") if raise_error
197
189
 
198
190
  respond_to do |format|
199
- format.html {
191
+ format.html {
200
192
  render "zuora_connect/static/error_handled", :locals => {
201
- :title => "Unauthorized",
193
+ :title => "Unauthorized",
202
194
  :message => "User is not an authorized admin for this application"
203
195
  }, status: 401, :layout => false
204
196
  }
205
- format.js {
197
+ format.js {
206
198
  render "zuora_connect/static/error_handled", :locals => {
207
- :title => "Unauthorized",
199
+ :title => "Unauthorized",
208
200
  :message => "User is not an authorized admin for this application"
209
- }, status: 401, :layout => false
201
+ }, status: 401, :layout => false
210
202
  }
211
203
  format.json { render json: {'errors' => ex.message}, status: 401 }
212
204
  format.all { render json: ex.message, status: 401 }
@@ -227,6 +219,80 @@ module ZuoraConnect
227
219
  return (request.headers['ZuoraCurrentEntity'].present? || cookies['ZuoraCurrentEntity'].present?)
228
220
  end
229
221
 
222
+ def create_new_instance
223
+ ZuoraConnect::AppInstance.read_master_db do
224
+ Thread.current[:appinstance] = nil
225
+ ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
226
+ Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
227
+
228
+ if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
229
+ ElasticAPM.set_label(:trace_id, request.uuid)
230
+ end
231
+
232
+ zuora_host = request.headers['zuora-host']
233
+ zuora_entity_id = (request.headers['zuora-entity-ids'] || '').gsub(
234
+ '-',
235
+ ''
236
+ ).split(',').first
237
+
238
+ # Validate host present
239
+ if zuora_host.blank?
240
+ render json: {
241
+ status: 401,
242
+ message: 'zuora-host header was not supplied.'
243
+ }, status: :unauthorized
244
+ return
245
+ end
246
+
247
+ # Validate entity-ids present
248
+ if zuora_entity_id.blank?
249
+ render json: {
250
+ status: 401,
251
+ message: 'zuora-entity-ids header was not supplied.'
252
+ }, status: :unauthorized
253
+ return
254
+ end
255
+
256
+ rest_domain = ZuoraAPI::Login.new(url: "https://#{zuora_host}").rest_domain
257
+ app_instance_id = ZuoraConnect::AppInstance.where(
258
+ 'zuora_entity_ids ?& array[:entities] AND zuora_domain = :host',
259
+ entities: [zuora_entity_id],
260
+ host: rest_domain
261
+ ).pluck(:id).first
262
+
263
+ if app_instance_id.present?
264
+ render json: {
265
+ status: 409,
266
+ message: 'Instance already exists.',
267
+ app_instance_id: app_instance_id
268
+ }, status: 409
269
+ else
270
+ Apartment::Tenant.switch!("public")
271
+ retry_count = 3
272
+ begin
273
+ @appinstance = new_instance(
274
+ next_instance_id,
275
+ zuora_entity_id,
276
+ rest_domain,
277
+ retry_count: retry_count
278
+ )
279
+ rescue ActiveRecord::RecordNotUnique
280
+ retry if (retry_count -= 1).positive?
281
+ return
282
+ end
283
+
284
+ app_instance_id = @appinstance.id
285
+ end
286
+
287
+ begin
288
+ Apartment::Tenant.switch!('public')
289
+ Apartment::Tenant.create(app_instance_id.to_s)
290
+ rescue Apartment::TenantExists
291
+ ZuoraConnect.logger.debug('Tenant Already Exists')
292
+ end
293
+ end
294
+ end
295
+
230
296
  private
231
297
  def setup_instance_via_prod_mode
232
298
  zuora_entity_id = request.headers['ZuoraCurrentEntity'] || cookies['ZuoraCurrentEntity']
@@ -234,7 +300,7 @@ module ZuoraConnect
234
300
  if zuora_entity_id.present?
235
301
  zuora_tenant_id = cookies['Zuora-Tenant-Id']
236
302
  zuora_user_id = cookies['Zuora-User-Id']
237
- zuora_host = request.headers["HTTP_X_FORWARDED_HOST"] || "apisandbox.zuora.com"
303
+ zuora_host = request.headers['HTTP_X_FORWARDED_HOST'] || request.headers['Zuora-Host'] || 'apisandbox.zuora.com'
238
304
 
239
305
  zuora_details = {'host' => zuora_host, 'user_id' => zuora_user_id, 'tenant_id' => zuora_tenant_id, 'entity_id' => zuora_entity_id}
240
306
  auth_headers = {}
@@ -246,7 +312,7 @@ module ZuoraConnect
246
312
  auth_headers.merge!({'Authorization' => "ZSession-a3N2w #{zuora_client.get_session(prefix: false, auth_type: :basic)}"})
247
313
  else
248
314
  render "zuora_connect/static/error_handled", :locals => {
249
- :title => "Missing Authorization Token",
315
+ :title => "Missing Authorization Token",
250
316
  :message => "Zuora 'Zuora-Auth-Token' header and 'ZSession' cookie not present."
251
317
  }, :layout => false
252
318
  return
@@ -268,27 +334,34 @@ module ZuoraConnect
268
334
  if zuora_tenant_id.to_s == "10548"
269
335
  session.clear
270
336
  render "zuora_connect/static/error_handled", :locals => {
271
- :title => "Security Testing",
337
+ :title => "Security Testing",
272
338
  :message => "Ya we know it you"
273
339
  }, :layout => false
274
340
  return
275
341
  else
276
- raise ZuoraConnect::Exceptions::Error.new("Header entity id does not match identity call entity id.")
342
+ raise ZuoraConnect::Exceptions::Error.new("Header entity id does not match identity call entity id.")
277
343
  end
278
344
  end
279
345
 
346
+ ##
347
+ # If the ZSession was refreshed, but it's still the same user and they aren't launching from the side bar,
348
+ # we don't need to continue
349
+ is_different_user = identity.slice("entityId", "tenantId", "userId", "userProfileId") == (session["ZuoraCurrentIdentity"] || {}).slice("entityId", "tenantId", "userId", "userProfileId")
350
+ zuora_details["identity"]["entityId"] = identity['entityId']
280
351
  session["ZuoraCurrentIdentity"] = identity
281
352
  session["ZuoraCurrentEntity"] = identity['entityId']
282
353
  session["ZSession"] = cookies['ZSession']
283
- zuora_instance_id = nil
284
- zuora_details["identity"]["entityId"] = identity['entityId']
285
-
286
- client_describe, response = zuora_client.rest_call(
287
- url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''),
288
- session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
289
- headers: auth_headers
290
- )
291
- session["ZuoraCurrentUserInfo"] = client_describe
354
+ if is_different_user || params[:sidebar_launch].to_s.to_bool
355
+ zuora_instance_id = nil
356
+ ZuoraConnect.logger.debug("UI Authorization", zuora: zuora_details)
357
+
358
+ client_describe, response = zuora_client.rest_call(
359
+ url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''),
360
+ session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
361
+ headers: auth_headers
362
+ )
363
+ session["ZuoraCurrentUserInfo"] = client_describe
364
+ end
292
365
  end
293
366
 
294
367
  #Find matching app instances.
@@ -296,7 +369,7 @@ module ZuoraConnect
296
369
  appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host AND id = :id", entities: [zuora_entity_id], host: zuora_client.rest_domain, id: zuora_instance_id.to_i).pluck(:id, :name)
297
370
  else
298
371
  #if app_instance_ids is present then permissions still controlled by connect
299
- if params[:app_instance_ids].present?
372
+ if params[:app_instance_ids].present?
300
373
  navbar, response = zuora_client.rest_call(url: zuora_client.rest_endpoint("navigation"))
301
374
  urls = navbar['menus'].map {|x| x['url']}
302
375
  app_env = ENV["DEIS_APP"] || "xyz123"
@@ -304,33 +377,39 @@ module ZuoraConnect
304
377
  if url.blank?
305
378
  if navbar['menus'].map {|x| x['label']}.include?('Link Connect Account')
306
379
  render "zuora_connect/static/error_handled", :locals => {
307
- :title => "Link Account",
380
+ :title => "Link Account",
308
381
  :message => "Link Connect account to gain access to application."
309
382
  }, :layout => false
310
383
  return
311
384
  end
312
- ZuoraConnect::Exceptions::APIError.new(message: "#{app_env} navbar url was blank", response: response)
385
+ raise ZuoraConnect::Exceptions::APIError.new(message: "#{app_env} navbar url was blank", response: response)
313
386
  else
314
- begin
315
- task_ids = JSON.parse(Base64.urlsafe_decode64(CGI.parse(URI.parse(url).query)["app_instance_ids"][0]))
316
- rescue => ex
317
- raise ZuoraConnect::Exceptions::APIError.new(message: "Failure in parsing the navbar urls.", response: response)
387
+ query_params = CGI.parse(URI.parse(url).query)
388
+ app_instance_ids = query_params["app_instance_ids"][0]
389
+ if app_instance_ids.present?
390
+ begin
391
+ task_ids = JSON.parse(Base64.urlsafe_decode64(app_instance_ids))
392
+
393
+ appinstances = ZuoraConnect::AppInstance.where(:id => task_ids).pluck(:id, :name)
394
+ rescue => ex
395
+ raise ZuoraConnect::Exceptions::APIError.new(message: "Failure in parsing the navbar urls.", response: response)
396
+ end
318
397
  end
319
398
  end
320
- appinstances = ZuoraConnect::AppInstance.where(:id => task_ids).pluck(:id, :name)
321
- else
322
- 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)
323
399
  end
400
+ 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)
324
401
  end
325
402
 
326
403
  zuora_user_id = cookies['Zuora-User-Id'] || session["ZuoraCurrentIdentity"]['userId']
327
404
 
328
- #One deployed instance
329
405
  if appinstances.size == 1
330
406
  ZuoraConnect.logger.debug("Instance is #{appinstances.to_h.keys.first}")
331
407
  @appinstance = ZuoraConnect::AppInstance.find(appinstances.to_h.keys.first)
408
+ end
332
409
 
333
- #Add user/update
410
+ # One deployed instance with credentials
411
+ if defined?(@appinstance) && @appinstance['zuora_logins'].present?
412
+ #Add user/update
334
413
  begin
335
414
  @zuora_user = ZuoraConnect::ZuoraUser.where(:zuora_user_id => zuora_user_id).first
336
415
  rescue ActiveRecord::StatementInvalid => ex
@@ -350,7 +429,7 @@ module ZuoraConnect
350
429
  else
351
430
  ZuoraConnect.logger.debug("New zuora user object for #{zuora_user_id}")
352
431
  @zuora_user = ZuoraConnect::ZuoraUser.create!(:zuora_user_id => zuora_user_id, :zuora_identity_response => {zuora_entity_id => session["ZuoraCurrentIdentity"]})
353
- end
432
+ end
354
433
  @zuora_user.session = session
355
434
  session["#{@appinstance.id}::user::localUserId"] = @zuora_user.id
356
435
  session["#{@appinstance.id}::user::email"] = session['ZuoraCurrentIdentity']["username"]
@@ -359,97 +438,103 @@ module ZuoraConnect
359
438
  session["appInstance"] = @appinstance.id
360
439
 
361
440
  #We have multiple, user must pick
362
- elsif appinstances.size > 1
441
+ elsif appinstances.size > 1
363
442
  ZuoraConnect.logger.debug("User must select instance. #{@names}")
364
443
  render "zuora_connect/static/launch", :locals => {:names => appinstances.to_h}, :layout => false
365
444
  return
366
445
 
367
446
  #We have no deployed instance for this tenant
368
- else
369
- #Ensure user can access oauth creation API
447
+ else
448
+ #Ensure user can access oauth creation API
370
449
  if !session["ZuoraCurrentUserInfo"]['permissions'].include?("permission.userManagement")
371
450
  Thread.current[:appinstance] = nil
372
451
  session["appInstance"] = nil
373
452
  render "zuora_connect/static/error_handled", :locals => {
374
- :title => "Application can only complete its initial setup via platform administrator",
453
+ :title => "Application can only complete its initial setup via platform administrator",
375
454
  :message => "Please contact admin who has user managment permissions in tenant and have them click and finish setup."
376
455
  }, :layout => false
377
456
  return
378
457
  end
379
458
  Apartment::Tenant.switch!("public")
380
- ActiveRecord::Base.transaction do
381
- ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
382
- 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)
459
+ retry_count = 3
460
+ task_data = {}
461
+ begin
462
+ ActiveRecord::Base.transaction do
463
+ ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
383
464
 
384
- if appinstances.size > 0
385
- redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
386
- return
387
- end
465
+ unless defined?(@appinstance)
466
+ 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)
388
467
 
389
- next_id = (ZuoraConnect::AppInstance.all.where('id > 24999999').order(id: :desc).limit(1).pluck(:id).first || 24999999) + 1
390
- user = (ENV['DEIS_APP'] || "Application").split('-').map(&:capitalize).join(' ')
391
- body = {
392
- 'userId' => zuora_user_id,
393
- 'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
394
- 'customAuthorities' => [],
395
- 'additionalInformation' => {
396
- 'description' => "This user is for #{user} application.",
397
- 'name' => "#{user} API User #{next_id}"
398
- }
399
- }
400
-
401
- oauth_response, response = zuora_client.rest_call(
402
- method: :post,
403
- body: body.to_json,
404
- url: zuora_client.rest_endpoint("genesis/clients").gsub('v1/', ''),
405
- session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
406
- headers: auth_headers
407
- )
468
+ if appinstances.size > 0
469
+ redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
470
+ return
471
+ end
472
+ end
408
473
 
409
- new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
410
- if session["ZuoraCurrentUserInfo"].blank?
411
- client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
412
- else
413
- client_describe = session["ZuoraCurrentUserInfo"]
414
- end
474
+ next_id = defined?(@appinstance) ? @appinstance.id : next_instance_id
475
+ if task_data.blank?
476
+ user = (ENV['DEIS_APP'] || "Application").split('-').map(&:capitalize).join(' ')
477
+ body = {
478
+ 'userId' => zuora_user_id,
479
+ 'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
480
+ 'customAuthorities' => [],
481
+ 'additionalInformation' => {
482
+ 'description' => "This user is for #{user} application.",
483
+ 'name' => "#{user} API User #{next_id}"
484
+ }
485
+ }
486
+
487
+ oauth_response, response = zuora_client.rest_call(
488
+ method: :post,
489
+ body: body.to_json,
490
+ url: zuora_client.rest_endpoint("genesis/clients").gsub('v1/', ''),
491
+ session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
492
+ headers: auth_headers
493
+ )
494
+
495
+ new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
496
+ if session["ZuoraCurrentUserInfo"].blank?
497
+ client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
498
+ else
499
+ client_describe = session["ZuoraCurrentUserInfo"]
500
+ end
501
+
502
+ available_entities = client_describe["accessibleEntities"].select {|entity| entity['id'] == zuora_entity_id}
503
+ task_data = {
504
+ "id": next_id,
505
+ "name": client_describe["tenantName"],
506
+ "mode": "Collections",
507
+ "status": "Running",
508
+ ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
509
+ "tenant_type": "Zuora",
510
+ "username": session["ZuoraCurrentIdentity"]["username"],
511
+ "url": new_zuora_client.url,
512
+ "status": "Active",
513
+ "oauth_client_id": oauth_response['clientId'],
514
+ "oauth_secret": oauth_response['clientSecret'],
515
+ "authentication_type": "OAUTH",
516
+ "entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
517
+ },
518
+ "tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
519
+ }
520
+ end
415
521
 
416
- available_entities = client_describe["accessibleEntities"].select {|entity| entity['id'] == zuora_entity_id}
417
- task_data = {
418
- "id": next_id,
419
- "name": client_describe["tenantName"],
420
- "mode": "Collections",
421
- "status": "Running",
422
- ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
423
- "tenant_type": "Zuora",
424
- "username": session["ZuoraCurrentIdentity"]["username"],
425
- "url": new_zuora_client.url,
426
- "status": "Active",
427
- "oauth_client_id": oauth_response['clientId'],
428
- "oauth_secret": oauth_response['clientSecret'],
429
- "authentication_type": "OAUTH",
430
- "entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
431
- },
432
- "tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
433
- }
434
- 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]}
435
- @appinstance = ZuoraConnect::AppInstance.new(mapped_values)
436
- retry_count = 0
437
- begin
438
- @appinstance.save(:validate => false)
439
- rescue ActiveRecord::RecordNotUnique => ex
440
- if (retry_count += 1) < 3
441
- @appinstance.assign_attributes({:api_token => rand(36**64).to_s(36), :token => rand(36**64).to_s(36)})
442
- retry
522
+ if defined?(@appinstance)
523
+ @appinstance.zuora_logins = task_data
524
+ @appinstance.save(:validate => false)
443
525
  else
444
- Thread.current[:appinstance] = nil
445
- session["appInstance"] = nil
446
- render "zuora_connect/static/error_handled", :locals => {
447
- :title => "Application could not create unique tokens.",
448
- :message => "Please contact support or retry launching application."
449
- }, :layout => false
450
- return
526
+ @appinstance = new_instance(
527
+ next_id,
528
+ zuora_entity_id,
529
+ zuora_client.rest_domain,
530
+ task_data: task_data,
531
+ retry_count: retry_count
532
+ )
451
533
  end
452
534
  end
535
+ rescue ActiveRecord::RecordNotUnique
536
+ retry if (retry_count -= 1).positive?
537
+ return
453
538
  end
454
539
 
455
540
  Apartment::Tenant.switch!("public")
@@ -472,19 +557,27 @@ module ZuoraConnect
472
557
  ZuoraConnect.logger.warn("UI Authorization Error", ex, zuora: zuora_details.merge({:error => response.body}))
473
558
  elsif final_error != "INVALID_SESSION"
474
559
  ZuoraConnect.logger.warn("UI Authorization Error", ex, zuora: zuora_details.merge({:error => final_error}))
560
+ else
561
+ ZuoraConnect.logger.info("UI Authorization Error", ex, zuora: zuora_details.merge({:error => final_error}))
475
562
  end
476
563
  redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
477
564
  return
478
- rescue => ex
479
- session.clear
480
- if defined?(ex.response) && ex.response.present? && defined?(ex.response.body)
481
- zuora_details.merge!({:error => ex.response.body})
565
+
566
+ rescue ZuoraAPI::Exceptions::ZuoraAPIError, Exception => ex
567
+ if ex.message.include?("Referenced User resource(s) not found") && ex.class == ZuoraAPI::Exceptions::ZuoraAPIError
568
+ locals = {title: "Provisioning Error", message: "New tenats need to be provisioned by API Gateway('#{ex.message}'). Please contact support."}
569
+ render "zuora_connect/static/error_handled", locals: locals, status: 400, layout: false
570
+ else
571
+ session.clear
572
+ if defined?(ex.response) && ex.response.present? && defined?(ex.response.body)
573
+ zuora_details.merge!({:error => ex.response.body})
574
+ end
575
+ ZuoraConnect.logger.error("UI Authorization Error", ex, zuora: zuora_details)
576
+ render "zuora_connect/static/error_unhandled", locals: {exception: ex, skip_exception: true}, layout: false, status: 500
482
577
  end
483
- ZuoraConnect.logger.error("UI Authorization Error", ex, zuora: zuora_details)
484
- render "zuora_connect/static/error_unhandled", locals: {exception: ex, skip_exception: true}, layout: false, status: 500
485
- return
578
+ return
486
579
  end
487
- elsif request["data"] && /^([A-Za-z0-9+\/\-\_]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/.match(request["data"].to_s)
580
+ elsif request["data"].present? && (request["connectInstanceId"].present? || /^([A-Za-z0-9+\/\-\_]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+-_\/]{3}=|[A-Za-z0-9+\/]{2}==)$/.match(request["data"].to_s))
488
581
  session.clear
489
582
  values = JSON.parse(ZuoraConnect::AppInstance.decrypt_response(Base64.urlsafe_decode64(request["data"])))
490
583
  values.fetch("param_data", {}).each do |k ,v|
@@ -499,8 +592,6 @@ module ZuoraConnect
499
592
  session["#{values["appInstance"]}::user::email"] = values["current_user"]["email"]
500
593
  end
501
594
 
502
- ZuoraConnect.logger.debug({msg: 'Setup values', connect: values}) if Rails.env != "production"
503
-
504
595
  @appinstance = ZuoraConnect::AppInstance.find_by(:id => values["appInstance"].to_i)
505
596
 
506
597
  if @appinstance.blank?
@@ -521,16 +612,53 @@ module ZuoraConnect
521
612
  else
522
613
  raise ZuoraConnect::Exceptions::AccessDenied.new("Authorization mismatch. Possible tampering with session.")
523
614
  end
524
- end
615
+ end
525
616
  else
526
617
  if session["appInstance"].present?
527
- @appinstance = ZuoraConnect::AppInstance.find_by(:id => session["appInstance"])
618
+ @appinstance = ZuoraConnect::AppInstance.find_by(:id => session["appInstance"])
528
619
  else
529
620
  raise ZuoraConnect::Exceptions::AccessDenied.new("No application state or session found.")
530
621
  end
531
622
  end
532
623
  end
533
624
 
625
+ def next_instance_id
626
+ min_instance_id = 24_999_999
627
+ (ZuoraConnect::AppInstance.all.where("id > #{min_instance_id}").order(id: :desc).limit(1).pluck(:id).first || min_instance_id) + 1
628
+ end
629
+
630
+ def new_instance(id, zuora_entity_id, rest_domain, task_data: nil, retry_count: 0)
631
+ app_instance = ZuoraConnect::AppInstance.new(
632
+ :id => id,
633
+ :api_token => generate_token,
634
+ :token => generate_token,
635
+ :zuora_logins => task_data,
636
+ :oauth_expires_at => Time.now + 1000.years,
637
+ :zuora_domain => rest_domain,
638
+ :zuora_entity_ids => [zuora_entity_id]
639
+ )
640
+
641
+ begin
642
+ app_instance.save(:validate => false)
643
+ rescue ActiveRecord::RecordNotUnique
644
+ raise if retry_count > 1
645
+
646
+ Thread.current[:appinstance] = nil
647
+ session['appInstance'] = nil
648
+ render 'zuora_connect/static/error_handled', :locals => {
649
+ :title => 'Application could not create unique tokens.',
650
+ :message => 'Please contact support or retry launching application.'
651
+ }, :layout => false
652
+ return
653
+ end
654
+
655
+ app_instance
656
+ end
657
+
658
+ def generate_token
659
+ rand(36**64).to_s(36)
660
+ end
661
+
534
662
  def setup_instance_via_dev_mode
535
663
  session["appInstance"] = ZuoraConnect.configuration.dev_mode_appinstance
536
664
  user = ZuoraConnect.configuration.dev_mode_user
@@ -16,10 +16,13 @@ module ZuoraConnect
16
16
  end
17
17
  end
18
18
 
19
+
19
20
  initializer :append_migrations do |app|
20
- unless app.root.to_s.match root.to_s
21
- config.paths["db/migrate"].expanded.each do |expanded_path|
22
- app.config.paths["db/migrate"] << expanded_path
21
+ if ZuoraConnect.configuration.insert_migrations
22
+ unless app.root.to_s.match root.to_s
23
+ config.paths["db/migrate"].expanded.each do |expanded_path|
24
+ app.config.paths["db/migrate"] << expanded_path
25
+ end
23
26
  end
24
27
  end
25
28
  end
@@ -13,6 +13,7 @@ module ZuoraConnect
13
13
  PATH_INFO
14
14
  CONTENT_TYPE
15
15
  ORIGINAL_FULLPATH
16
+ QUERY_STRING
16
17
  )
17
18
 
18
19
  config.before_initialize do
@@ -46,7 +47,7 @@ module ZuoraConnect
46
47
  require 'lograge'
47
48
 
48
49
  Rails.configuration.logger = ZuoraConnect.custom_logger(name: "Rails")
49
- if Rails.env != 'development'
50
+ if !Rails.env.test? && !Rails.env.development?
50
51
  Rails.configuration.lograge.enabled = true
51
52
  Rails.configuration.colorize_logging = false
52
53
  end
@@ -1,3 +1,3 @@
1
1
  module ZuoraConnect
2
- VERSION = "2.0.57"
2
+ VERSION = "2.0.58a"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zuora_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.57
4
+ version: 2.0.58a
5
5
  platform: ruby
6
6
  authors:
7
7
  - Connect Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-13 00:00:00.000000000 Z
11
+ date: 2020-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: apartment
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: ougai-formatters-customizable
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 1.0.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 1.0.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: zuora_api
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +120,20 @@ dependencies:
120
120
  - - ">="
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0'
123
+ - !ruby/object:Gem::Dependency
124
+ name: aws-sdk-rails
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ type: :runtime
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
123
137
  - !ruby/object:Gem::Dependency
124
138
  name: mono_logger
125
139
  requirement: !ruby/object:Gem::Requirement
@@ -415,9 +429,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
415
429
  version: '0'
416
430
  required_rubygems_version: !ruby/object:Gem::Requirement
417
431
  requirements:
418
- - - ">="
432
+ - - ">"
419
433
  - !ruby/object:Gem::Version
420
- version: '0'
434
+ version: 1.3.1
421
435
  requirements: []
422
436
  rubygems_version: 3.0.3
423
437
  signing_key: