zuora_connect 2.0.57 → 2.0.58a

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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: