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 +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:
|