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 +4 -4
- data/app/assets/javascripts/hallway_wrapper/after.js +22 -3
- data/app/controllers/zuora_connect/static_controller.rb +35 -10
- data/app/models/zuora_connect/app_instance_base.rb +49 -34
- data/app/views/zuora_connect/static/launch.html.erb +8 -11
- data/config/routes.rb +4 -0
- data/lib/resque/plugins/app_instance_job.rb +7 -3
- data/lib/zuora_connect.rb +2 -0
- data/lib/zuora_connect/configuration.rb +3 -2
- data/lib/zuora_connect/controllers/helpers.rb +258 -130
- data/lib/zuora_connect/engine.rb +6 -3
- data/lib/zuora_connect/railtie.rb +2 -1
- data/lib/zuora_connect/version.rb +1 -1
- metadata +22 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a03cd7450b81983c6d782fe911babc655153094bf6ff41fec0b3ed3a3a06888
|
4
|
+
data.tar.gz: 99eff46c23e53cd0d09b4c0fdafe199c239f800ca55dcaed255674d69729a2db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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("
|
14
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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.
|
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
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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;
|
data/config/routes.rb
CHANGED
@@ -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
|
-
|
28
|
-
|
29
|
-
|
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
|
(
|
data/lib/zuora_connect.rb
CHANGED
@@ -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.
|
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[
|
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
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
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
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
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
|
-
|
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
|
-
|
381
|
-
|
382
|
-
|
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
|
-
|
385
|
-
|
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
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
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
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
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
|
-
|
417
|
-
|
418
|
-
|
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
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
:
|
449
|
-
|
450
|
-
|
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
|
-
|
479
|
-
|
480
|
-
if
|
481
|
-
|
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
|
-
|
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
|
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
|
data/lib/zuora_connect/engine.rb
CHANGED
@@ -16,10 +16,13 @@ module ZuoraConnect
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
|
19
20
|
initializer :append_migrations do |app|
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
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
|
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.
|
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-
|
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:
|
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:
|
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:
|
434
|
+
version: 1.3.1
|
421
435
|
requirements: []
|
422
436
|
rubygems_version: 3.0.3
|
423
437
|
signing_key:
|