zuora_connect 2.0.5 → 2.0.8
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/controllers/zuora_connect/static_controller.rb +4 -17
- data/app/helpers/zuora_connect/application_helper.rb +10 -0
- data/app/models/zuora_connect/app_instance_base.rb +109 -66
- data/app/models/zuora_connect/telegraf.rb +2 -2
- data/app/models/zuora_connect/zuora_user.rb +1 -0
- data/app/views/zuora_connect/static/error_handled.html.erb +77 -0
- data/app/views/zuora_connect/static/error_unhandled.erb +82 -0
- data/app/views/zuora_connect/static/launch.html.erb +74 -75
- data/config/initializers/patches.rb +9 -0
- data/config/routes.rb +0 -2
- data/db/migrate/20190520232222_add_unique_index.rb +6 -0
- data/lib/middleware/json_parse_errors.rb +22 -0
- data/lib/middleware/request_id_middleware.rb +1 -1
- data/lib/resque/dynamic_queues.rb +5 -1
- data/lib/resque/plugins/custom_logger.rb +1 -1
- data/lib/zuora_connect.rb +59 -42
- data/lib/zuora_connect/configuration.rb +3 -3
- data/lib/zuora_connect/controllers/helpers.rb +253 -183
- data/lib/zuora_connect/engine.rb +2 -1
- data/lib/zuora_connect/railtie.rb +10 -6
- data/lib/zuora_connect/version.rb +1 -1
- metadata +52 -52
- data/app/views/zuora_connect/static/invalid_app_instance_error.html.erb +0 -65
- data/app/views/zuora_connect/static/invalid_launch_request.html.erb +0 -81
- data/app/views/zuora_connect/static/permission_error.html.erb +0 -80
- data/app/views/zuora_connect/static/session_error.html.erb +0 -63
- data/lib/zuora_connect/views/helpers.rb +0 -9
@@ -3,11 +3,11 @@ module ZuoraConnect
|
|
3
3
|
|
4
4
|
attr_accessor :default_locale, :default_time_zone, :url, :mode, :delayed_job,:private_key, :additional_apartment_models
|
5
5
|
|
6
|
-
attr_accessor :enable_metrics, :telegraf_endpoint, :telegraf_debug, :custom_prometheus_update_block, :silencer_resque_finish, :blpop_queue
|
6
|
+
attr_accessor :enable_metrics, :telegraf_endpoint, :telegraf_debug, :custom_prometheus_update_block, :silencer_resque_finish, :blpop_queue
|
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
|
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
|
11
11
|
|
12
12
|
def initialize
|
13
13
|
@default_locale = :en
|
@@ -19,7 +19,6 @@ module ZuoraConnect
|
|
19
19
|
@additional_apartment_models = []
|
20
20
|
@silencer_resque_finish = true
|
21
21
|
@blpop_queue = false
|
22
|
-
@app_access_permissions = false
|
23
22
|
|
24
23
|
# Setting the app name for telegraf write
|
25
24
|
@enable_metrics = false
|
@@ -43,6 +42,7 @@ module ZuoraConnect
|
|
43
42
|
@aws_region = "us-west-2"
|
44
43
|
@s3_bucket_name = "rbm-apps"
|
45
44
|
@s3_folder_name = Rails.application.class.parent_name
|
45
|
+
@json_logging = Rails.env.to_s == 'development' ? false : true
|
46
46
|
end
|
47
47
|
|
48
48
|
def private_key
|
@@ -16,7 +16,7 @@ module ZuoraConnect
|
|
16
16
|
ZuoraConnect.logger.debug("[#{@appinstance.id}] API REQUEST - API token") if @appinstance.present?
|
17
17
|
check_instance
|
18
18
|
elsif ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(request.headers.fetch("HOST", nil))
|
19
|
-
zuora_host, zuora_entity_id, zuora_instance_id = [request.headers['zuora-host'], request.headers['zuora-entity-ids'].gsub('-',''), request.headers['zuora-instance-id']]
|
19
|
+
zuora_host, zuora_entity_id, zuora_instance_id = [request.headers['zuora-host'], (request.headers['zuora-entity-ids'] || "").gsub('-',''), request.headers['zuora-instance-id']]
|
20
20
|
|
21
21
|
#Validate host present
|
22
22
|
if zuora_host.blank?
|
@@ -37,21 +37,24 @@ module ZuoraConnect
|
|
37
37
|
|
38
38
|
if appinstances.size == 0
|
39
39
|
render json: {"status": 401, "message": "Missing mapping or no deployment for '#{zuora_host}-#{zuora_entity_id}' ."}, status: :unauthorized
|
40
|
+
return
|
40
41
|
elsif appinstances.size > 1
|
41
42
|
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
|
43
|
+
return
|
42
44
|
else
|
43
45
|
@appinstance = appinstances.first
|
46
|
+
check_instance
|
44
47
|
end
|
45
|
-
|
46
|
-
|
48
|
+
|
49
|
+
elsif request.headers.fetch("Authorization", "").include?("Basic ")
|
47
50
|
authenticate_or_request_with_http_basic do |username, password|
|
48
51
|
@appinstance = ZuoraConnect::AppInstance.where(:token => password).first
|
49
52
|
@appinstance ||= ZuoraConnect::AppInstance.where(:api_token => password).first
|
50
53
|
ZuoraConnect.logger.debug("[#{@appinstance.id}] API REQUEST - Basic Auth") if @appinstance.present?
|
51
54
|
check_instance
|
52
55
|
end
|
53
|
-
|
54
|
-
|
56
|
+
else
|
57
|
+
check_instance
|
55
58
|
end
|
56
59
|
|
57
60
|
if @appinstance.present?
|
@@ -59,175 +62,253 @@ module ZuoraConnect
|
|
59
62
|
end
|
60
63
|
end
|
61
64
|
|
65
|
+
#API ONLY
|
66
|
+
def check_instance
|
67
|
+
if defined?(@appinstance) && @appinstance.present?
|
68
|
+
if @appinstance.new_session_for_api_requests(:params => params)
|
69
|
+
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
70
|
+
end
|
71
|
+
Thread.current[:appinstance] = @appinstance
|
72
|
+
PaperTrail.whodunnit = "API User" if defined?(PaperTrail)
|
73
|
+
ElasticAPM.set_user("API User") if defined?(ElasticAPM) && ElasticAPM.running?
|
74
|
+
return true
|
75
|
+
else
|
76
|
+
response.set_header('WWW-Authenticate', "Basic realm=\"Application\"")
|
77
|
+
render json: {"status": 401, "message": "Access Denied"}, status: :unauthorized
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
62
82
|
def authenticate_connect_app_request
|
63
83
|
ElasticAPM.set_tag(:trace_id, request.uuid) if defined?(ElasticAPM) && ElasticAPM.running?
|
64
84
|
Thread.current[:appinstance] = nil
|
85
|
+
start_time = Time.now
|
65
86
|
|
66
|
-
if
|
67
|
-
|
68
|
-
#Do we need to refresh session identity
|
69
|
-
zuora_host = request.headers["HTTP_X_FORWARDED_HOST"] || "apisandbox.zuora.com"
|
70
|
-
if request.headers["Zuora-Auth-Token"].present?
|
71
|
-
zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", bearer_token: request.headers["Zuora-Auth-Token"], oauth_session_expires_at: Time.now + 5.minutes )
|
72
|
-
elsif cookies['ZSession'].present?
|
73
|
-
zuora_client = ZuoraAPI::Basic.new(url: "https://#{zuora_host}", session: cookies['ZSession'])
|
74
|
-
else
|
75
|
-
raise ZuoraConnect::Exceptions::Error.new("Neither the ZSession cookie nor the Zuora-Auth-Token are present in payload.")
|
76
|
-
end
|
77
|
-
zuora_entity_id = request.headers['ZuoraCurrentEntity']
|
78
|
-
zuora_instance_id = params[:sidebar_launch].to_bool ? nil : (params[:app_instance_id] || session["appInstance"])
|
87
|
+
if ZuoraConnect.configuration.mode == "Production"
|
88
|
+
zuora_entity_id = request.headers['ZuoraCurrentEntity'] || cookies['ZuoraCurrentEntity']
|
79
89
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
session["ZuoraCurrentIdentity"] = identity
|
85
|
-
session["ZuoraCurrentEntity"] = identity['entityId']
|
90
|
+
if zuora_entity_id.present?
|
91
|
+
zuora_tenant_id = cookies['Zuora-Tenant-Id']
|
92
|
+
zuora_user_id = cookies['Zuora-User-Id']
|
93
|
+
zuora_host = request.headers["HTTP_X_FORWARDED_HOST"] || "apisandbox.zuora.com"
|
86
94
|
|
87
|
-
|
88
|
-
rescue => ex
|
89
|
-
ZuoraConnect.logger.error(ex)
|
90
|
-
render "zuora_connect/static/invalid_launch_request", :locals => {:exception => ex}
|
91
|
-
return
|
92
|
-
end
|
93
|
-
end
|
95
|
+
zuora_details = {'host' => zuora_host, 'user_id' => zuora_user_id, 'tenant_id' => zuora_tenant_id, 'entity_id' => zuora_entity_id}
|
94
96
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
if params[:app_instance_ids].present?
|
101
|
-
begin
|
102
|
-
navbar, response = zuora_client.rest_call(url: zuora_client.rest_endpoint("navigation"))
|
103
|
-
urls = navbar['menus'].map {|x| x['url']}
|
104
|
-
app_env = ENV["DEIS_APP"] || "xyz123"
|
105
|
-
url = urls.compact.select {|url| File.basename(url).start_with?(app_env + '?')}.first
|
106
|
-
task_ids = JSON.parse(Base64.urlsafe_decode64(CGI.parse(URI.parse(url).query)["app_instance_ids"][0]))
|
107
|
-
|
108
|
-
appinstances = ZuoraConnect::AppInstance.where(:id => task_ids).pluck(:id, :name)
|
109
|
-
rescue => ex
|
110
|
-
ZuoraConnect.logger.error(ex)
|
111
|
-
render "zuora_connect/static/invalid_launch_request", :locals => {:exception => ex}
|
112
|
-
return
|
113
|
-
end
|
97
|
+
#Do we need to refresh session identity
|
98
|
+
if request.headers["Zuora-Auth-Token"].present?
|
99
|
+
zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", bearer_token: request.headers["Zuora-Auth-Token"], oauth_session_expires_at: Time.now + 5.minutes )
|
100
|
+
elsif cookies['ZSession'].present?
|
101
|
+
zuora_client = ZuoraAPI::Basic.new(url: "https://#{zuora_host}", session: cookies['ZSession'])
|
114
102
|
else
|
115
|
-
|
103
|
+
render "zuora_connect/static/error_handled", :locals => {
|
104
|
+
:title => "Missing Authorization Token",
|
105
|
+
:message => "Zuora 'Zuora-Auth-Token' header and 'ZSession' cookie not present."
|
106
|
+
}, :layout => false
|
107
|
+
return
|
116
108
|
end
|
117
|
-
end
|
118
109
|
|
119
|
-
|
110
|
+
begin
|
111
|
+
zuora_instance_id = params[:sidebar_launch].to_s.to_bool ? nil : (params[:app_instance_id] || session["appInstance"])
|
112
|
+
|
113
|
+
#Identity blank or current entity different
|
114
|
+
different_zsession = session["ZSession"] != cookies['ZSession']
|
115
|
+
missmatched_entity = session["ZuoraCurrentEntity"] != zuora_entity_id
|
116
|
+
missing_identity = session["ZuoraCurrentIdentity"].blank?
|
120
117
|
|
121
|
-
|
122
|
-
|
123
|
-
|
118
|
+
if (missing_identity || missmatched_entity || different_zsession)
|
119
|
+
zuora_details.merge!({'identity' => {'different_zsession' => different_zsession, 'missing_identity' => missing_identity, 'missmatched_entity' => missmatched_entity}})
|
120
|
+
identity, response = zuora_client.rest_call(url: zuora_client.rest_endpoint("identity"))
|
121
|
+
session["ZuoraCurrentIdentity"] = identity
|
122
|
+
session["ZuoraCurrentEntity"] = identity['entityId']
|
123
|
+
session["ZSession"] = cookies['ZSession']
|
124
|
+
zuora_instance_id = nil
|
125
|
+
zuora_details["identity"]["entityId"] = identity['entityId']
|
124
126
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
if @user.updated_at < Time.now - 1.day
|
130
|
-
@user.zuora_identity_response[zuora_entity_id] = session["ZuoraCurrentIdentity"]
|
131
|
-
@user.save!
|
127
|
+
client_describe, response = zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic, headers: zuora_client.class == ZuoraAPI::Oauth ? {} : {'Authorization' => "ZSession-a3N2w #{zuora_client.get_session(prefix: false, auth_type: :basic)}"})
|
128
|
+
session["ZuoraCurrentUserInfo"] = client_describe
|
129
|
+
|
130
|
+
raise ZuoraConnect::Exceptions::Error.new("Header entity id does not match identity call entity id.") if zuora_entity_id != identity['entityId']
|
132
131
|
end
|
133
|
-
else
|
134
|
-
ZuoraConnect.logger.debug("New zuora user object for #{zuora_user_id}")
|
135
|
-
@user = ZuoraConnect::ZuoraUser.create!(:zuora_user_id => zuora_user_id, :zuora_identity_response => {zuora_entity_id => session["ZuoraCurrentIdentity"]})
|
136
|
-
end
|
137
|
-
#Update access if admin in tenant
|
138
|
-
if session["ZuoraCurrentIdentity"]['platformRole'] == 'ADMIN' && !@user.app_permissions['access'].to_bool
|
139
|
-
@user.app_permissions['access'] = true
|
140
|
-
@user.save!
|
141
|
-
end
|
142
132
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
begin
|
160
|
-
#Ensure user can access oauth creation API
|
161
|
-
if session["ZuoraCurrentIdentity"]['platformRole'] != 'ADMIN'
|
162
|
-
raise ZuoraConnect::Exceptions::Error.new("User is not admin, workflow cannot be deployed.")
|
133
|
+
#Find matching app instances.
|
134
|
+
if zuora_instance_id.present?
|
135
|
+
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).pluck(:id, :name)
|
136
|
+
else
|
137
|
+
#if app_instance_ids is present then permissions still controlled by connect
|
138
|
+
if params[:app_instance_ids].present?
|
139
|
+
navbar, response = zuora_client.rest_call(url: zuora_client.rest_endpoint("navigation"))
|
140
|
+
urls = navbar['menus'].map {|x| x['url']}
|
141
|
+
app_env = ENV["DEIS_APP"] || "xyz123"
|
142
|
+
url = urls.compact.select {|url| File.basename(url).start_with?(app_env + '?')}.first
|
143
|
+
task_ids = JSON.parse(Base64.urlsafe_decode64(CGI.parse(URI.parse(url).query)["app_instance_ids"][0]))
|
144
|
+
|
145
|
+
appinstances = ZuoraConnect::AppInstance.where(:id => task_ids).pluck(:id, :name)
|
146
|
+
else
|
147
|
+
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)
|
148
|
+
end
|
163
149
|
end
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
150
|
+
|
151
|
+
zuora_user_id = cookies['Zuora-User-Id'] || session["ZuoraCurrentIdentity"]['userId']
|
152
|
+
|
153
|
+
#One deployed instance
|
154
|
+
if appinstances.size == 1
|
155
|
+
ZuoraConnect.logger.debug("Instance is #{appinstances.to_h.keys.first}")
|
156
|
+
@appinstance = ZuoraConnect::AppInstance.find(appinstances.to_h.keys.first)
|
157
|
+
|
158
|
+
#Add user/update
|
159
|
+
@zuora_user = ZuoraConnect::ZuoraUser.where(:zuora_user_id => zuora_user_id).first
|
160
|
+
if @zuora_user.present?
|
161
|
+
ZuoraConnect.logger.debug("Current zuora user #{zuora_user_id}")
|
162
|
+
if @zuora_user.updated_at < Time.now - 1.day
|
163
|
+
@zuora_user.zuora_identity_response[zuora_entity_id] = session["ZuoraCurrentIdentity"]
|
164
|
+
@zuora_user.save!
|
165
|
+
end
|
166
|
+
else
|
167
|
+
ZuoraConnect.logger.debug("New zuora user object for #{zuora_user_id}")
|
168
|
+
@zuora_user = ZuoraConnect::ZuoraUser.create!(:zuora_user_id => zuora_user_id, :zuora_identity_response => {zuora_entity_id => session["ZuoraCurrentIdentity"]})
|
169
|
+
end
|
170
|
+
@zuora_user.session = session
|
171
|
+
session["#{@appinstance.id}::user::email"] = session['ZuoraCurrentIdentity']["username"]
|
172
|
+
session["#{@appinstance.id}::user::timezone"] = session['ZuoraCurrentIdentity']["timeZone"]
|
173
|
+
session["#{@appinstance.id}::user::locale"] = session['ZuoraCurrentIdentity']["language"]
|
174
|
+
session["appInstance"] = @appinstance.id
|
175
|
+
|
176
|
+
#We have multiple, user must pick
|
177
|
+
elsif appinstances.size > 1
|
178
|
+
ZuoraConnect.logger.debug("User must select instance. #{@names}")
|
179
|
+
render "zuora_connect/static/launch", :locals => {:names => appinstances.to_h}, :layout => false
|
180
|
+
return
|
181
|
+
|
182
|
+
#We have no deployed instance for this tenant
|
183
|
+
else
|
184
|
+
#Ensure user can access oauth creation API
|
185
|
+
if session["ZuoraCurrentIdentity"]['platformRole'] != 'ADMIN'
|
186
|
+
Thread.current[:appinstance] = nil
|
187
|
+
session["appInstance"] = nil
|
188
|
+
render "zuora_connect/static/error_handled", :locals => {
|
189
|
+
:title => "Application can only complete its initial setup via platform administrator",
|
190
|
+
:message => "Please contact admin of tenant and have them click on link again to launch application."
|
191
|
+
}, :layout => false
|
192
|
+
return
|
193
|
+
end
|
194
|
+
Apartment::Tenant.switch!("public")
|
195
|
+
ActiveRecord::Base.transaction do
|
196
|
+
ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
|
197
|
+
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)
|
198
|
+
|
199
|
+
if appinstances.size > 0
|
200
|
+
redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
|
201
|
+
return
|
202
|
+
end
|
203
|
+
|
204
|
+
next_id = (ZuoraConnect::AppInstance.all.where('id > 24999999').order(id: :desc).limit(1).pluck(:id).first || 24999999) + 1
|
205
|
+
user = (ENV['DEIS_APP'] || "Application").split('-').map(&:capitalize).join(' ')
|
206
|
+
body = {
|
207
|
+
'userId' => zuora_user_id,
|
208
|
+
'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
|
209
|
+
'customAuthorities' => [],
|
210
|
+
'additionalInformation' => {
|
211
|
+
'description' => "This user is for #{user} application.",
|
212
|
+
'name' => "#{user} API User #{next_id}"
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
oauth_response, response = zuora_client.rest_call(method: :post, body: body.to_json, url: zuora_client.rest_endpoint("genesis/clients").gsub('v1/', ''), session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic, headers: zuora_client.class == ZuoraAPI::Oauth ? {} : {'Authorization' => "ZSession-a3N2w #{zuora_client.get_session(prefix: false, auth_type: :basic)}"})
|
217
|
+
|
218
|
+
new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
|
219
|
+
if session["ZuoraCurrentUserInfo"].blank?
|
220
|
+
client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
|
221
|
+
else
|
222
|
+
client_describe = session["ZuoraCurrentUserInfo"]
|
223
|
+
end
|
224
|
+
|
225
|
+
available_entities = client_describe["accessibleEntities"].select {|entity| entity['id'] == zuora_entity_id}
|
226
|
+
task_data = {
|
227
|
+
"id": next_id,
|
228
|
+
"name": client_describe["tenantName"],
|
229
|
+
"mode": "Collections",
|
230
|
+
"status": "Running",
|
231
|
+
ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
|
232
|
+
"tenant_type": "Zuora",
|
233
|
+
"username": session["ZuoraCurrentIdentity"]["username"],
|
234
|
+
"url": new_zuora_client.url,
|
235
|
+
"status": "Active",
|
236
|
+
"oauth_client_id": oauth_response['clientId'],
|
237
|
+
"oauth_secret": oauth_response['clientSecret'],
|
238
|
+
"authentication_type": "OAUTH",
|
239
|
+
"entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
|
240
|
+
},
|
241
|
+
"tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
|
242
|
+
}
|
243
|
+
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]}
|
244
|
+
@appinstance = ZuoraConnect::AppInstance.new(mapped_values)
|
245
|
+
retry_count = 0
|
246
|
+
begin
|
247
|
+
@appinstance.save(:validate => false)
|
248
|
+
rescue ActiveRecord::RecordNotUnique => ex
|
249
|
+
if (retry_count += 1) < 3
|
250
|
+
@appinstance.assign_attributes({:api_token => rand(36**64).to_s(36), :token => rand(36**64).to_s(36)})
|
251
|
+
retry
|
252
|
+
else
|
253
|
+
Thread.current[:appinstance] = nil
|
254
|
+
session["appInstance"] = nil
|
255
|
+
render "zuora_connect/static/error_handled", :locals => {
|
256
|
+
:title => "Application could not create unique tokens.",
|
257
|
+
:message => "Please contact support or retry launching application."
|
258
|
+
}, :layout => false
|
259
|
+
return
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
Apartment::Tenant.switch!("public")
|
265
|
+
begin
|
266
|
+
Apartment::Tenant.create(@appinstance.id.to_s)
|
267
|
+
rescue Apartment::TenantExists => ex
|
268
|
+
ZuoraConnect.logger.debug("Tenant Already Exists")
|
269
|
+
end
|
270
|
+
@appinstance.refresh
|
271
|
+
session["appInstance"] = @appinstance.id
|
187
272
|
end
|
188
273
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
"url": new_zuora_client.url,
|
198
|
-
"status": "Active",
|
199
|
-
"oauth_client_id": oauth_response['clientId'],
|
200
|
-
"oauth_secret": oauth_response['clientSecret'],
|
201
|
-
"authentication_type": "OAUTH",
|
202
|
-
"entities": client_describe["accessibleEntities"].map {|e| e.merge({'displayName' => client_describe["tenantName"]})} #needs work
|
203
|
-
},
|
204
|
-
"tenant_ids": client_describe["accessibleEntities"].map{|e| e['entityId'] }.push(client_describe["tenantId"]).uniq,
|
205
|
-
}
|
206
|
-
|
207
|
-
appinstance = ZuoraConnect::AppInstance.new(:id => next_id, :zuora_logins => task_data.to_json, :oauth_expires_at => Time.now + 1000.years)
|
208
|
-
appinstance.save(:validate => false)
|
209
|
-
@appinstance = ZuoraConnect::AppInstance.find(appinstance.id)
|
210
|
-
@appinstance.apartment_switch(method = nil, migrate = true)
|
211
|
-
|
212
|
-
session["appInstance"] = @appinstance.id
|
213
|
-
rescue => ex
|
214
|
-
ZuoraConnect.logger.error(ex)
|
215
|
-
render "zuora_connect/static/invalid_launch_request", :locals => {:exception => ex}
|
274
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
275
|
+
output_xml, input_xml = zuora_client.soap_call(errors: [], z_session: false) do |xml|
|
276
|
+
xml['api'].getUserInfo
|
277
|
+
end
|
278
|
+
final_error = output_xml.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text
|
279
|
+
session.clear
|
280
|
+
ZuoraConnect.logger.warn(ex, zuora: zuora_details.merge({:error => final_error}))
|
281
|
+
redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
|
216
282
|
return
|
283
|
+
rescue => ex
|
284
|
+
ZuoraConnect.logger.error(ex, zuora: zuora_details)
|
285
|
+
render "zuora_connect/static/error_unhandled", :locals => {:exception => ex}, :layout => false
|
286
|
+
return
|
217
287
|
end
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
start_time = Time.now
|
222
|
-
if ZuoraConnect.configuration.mode == "Production"
|
223
|
-
if request["data"] && /^([A-Za-z0-9+\/\-\_]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/.match(request["data"].to_s)
|
288
|
+
elsif request["data"] && /^([A-Za-z0-9+\/\-\_]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/.match(request["data"].to_s)
|
224
289
|
setup_instance_via_data
|
225
290
|
else
|
226
|
-
|
291
|
+
if session["appInstance"].present?
|
292
|
+
@appinstance = ZuoraConnect::AppInstance.where(:id => session["appInstance"]).first
|
293
|
+
else
|
294
|
+
render "zuora_connect/static/error_handled", :locals => {
|
295
|
+
:title => "Application state could not be verified",
|
296
|
+
:message => "Please relaunch application."
|
297
|
+
}, :layout => false
|
298
|
+
return
|
299
|
+
end
|
227
300
|
end
|
228
301
|
else
|
229
302
|
setup_instance_via_dev_mode
|
230
303
|
end
|
304
|
+
|
305
|
+
if !defined?(@appinstance) || @appinstance.blank?
|
306
|
+
render "zuora_connect/static/error_handled", :locals => {
|
307
|
+
:title => "Application state could not be found.",
|
308
|
+
:message => "Please relaunch application."
|
309
|
+
}, :layout => false
|
310
|
+
return
|
311
|
+
end
|
231
312
|
#Call .data_lookup with the current session to retrieve session. In some cases session may be stored/cache in redis
|
232
313
|
#so data lookup provides a model method that can be overriden per app.
|
233
314
|
if params[:controller] != 'zuora_connect/api/v1/app_instance' && params[:action] != 'drop'
|
@@ -235,16 +316,23 @@ module ZuoraConnect
|
|
235
316
|
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
236
317
|
end
|
237
318
|
end
|
319
|
+
|
238
320
|
if session["#{@appinstance.id}::user::email"].present?
|
239
321
|
ElasticAPM.set_user(session["#{@appinstance.id}::user::email"]) if defined?(ElasticAPM) && ElasticAPM.running?
|
240
322
|
PaperTrail.whodunnit = session["#{@appinstance.id}::user::email"] if defined?(PaperTrail)
|
241
323
|
end
|
242
324
|
begin
|
243
|
-
|
325
|
+
locale = session["#{@appinstance.id}::user::locale"]
|
326
|
+
I18n.locale = locale.present? ? locale : @appinstance.locale
|
244
327
|
rescue I18n::InvalidLocale => ex
|
245
328
|
ZuoraConnect.logger.error(ex) if !ZuoraConnect::AppInstance::IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
|
246
329
|
end
|
247
|
-
|
330
|
+
begin
|
331
|
+
Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
|
332
|
+
rescue
|
333
|
+
ZuoraConnect.logger.error(ex)
|
334
|
+
end
|
335
|
+
|
248
336
|
ZuoraConnect.logger.debug("[#{@appinstance.blank? ? "N/A" : @appinstance.id}] Authenticate App Request Completed In - #{(Time.now - start_time).round(2)}s")
|
249
337
|
end
|
250
338
|
|
@@ -266,6 +354,14 @@ module ZuoraConnect
|
|
266
354
|
return session["#{@appinstance.id}::admin"]
|
267
355
|
end
|
268
356
|
|
357
|
+
def zuora_user
|
358
|
+
return @zuora_user
|
359
|
+
end
|
360
|
+
|
361
|
+
def hallway_integration?
|
362
|
+
return (request.headers['ZuoraCurrentEntity'].present? || cookies['ZuoraCurrentEntity'].present?)
|
363
|
+
end
|
364
|
+
|
269
365
|
private
|
270
366
|
def setup_instance_via_data
|
271
367
|
session.clear
|
@@ -287,6 +383,7 @@ module ZuoraConnect
|
|
287
383
|
ZuoraConnect.logger.debug({msg: 'Setup values', connect: values}) if Rails.env != "production"
|
288
384
|
|
289
385
|
@appinstance = ZuoraConnect::AppInstance.where(:id => values["appInstance"].to_i).first
|
386
|
+
|
290
387
|
if @appinstance.blank?
|
291
388
|
Apartment::Tenant.switch!("public")
|
292
389
|
begin
|
@@ -294,29 +391,20 @@ module ZuoraConnect
|
|
294
391
|
rescue Apartment::TenantExists => ex
|
295
392
|
ZuoraConnect.logger.debug("Tenant Already Exists")
|
296
393
|
end
|
297
|
-
|
394
|
+
mapped_values = {:api_token => values['api_token'], :token => values['api_token'], :access_token => values["access_token"], :refresh_token => values["refresh_token"], :oauth_expires_at => values["expires"]}
|
395
|
+
@appinstance = ZuoraConnect::AppInstance.new(mapped_values.merge({:id => values["appInstance"].to_i}))
|
298
396
|
@appinstance.save(:validate => false)
|
299
397
|
else
|
300
|
-
|
301
|
-
@appinstance.
|
302
|
-
@appinstance.oauth_expires_at = values["expires"] if !values["expires"].blank?
|
303
|
-
@appinstance.api_token = values["api_token"] if !values["api_token"].blank? && @appinstance.api_token != values["api_token"]
|
398
|
+
mapped_values = {:access_token => values["access_token"], :refresh_token => values["refresh_token"], :oauth_expires_at => values["expires"]}
|
399
|
+
@appinstance.assign_attributes(mapped_values)
|
304
400
|
if @appinstance.access_token_changed? && @appinstance.refresh_token_changed?
|
305
401
|
@appinstance.save(:validate => false)
|
306
402
|
else
|
307
|
-
raise ZuoraConnect::Exceptions::AccessDenied.new("Authorization
|
403
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("Authorization mismatch. Possible tampering")
|
308
404
|
end
|
309
405
|
end
|
310
406
|
end
|
311
407
|
|
312
|
-
def setup_instance_via_session
|
313
|
-
if session["appInstance"].present?
|
314
|
-
@appinstance = ZuoraConnect::AppInstance.where(:id => session["appInstance"]).first
|
315
|
-
else
|
316
|
-
raise ZuoraConnect::Exceptions::SessionInvalid.new("Session Blank -- Relaunch Application")
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
408
|
def setup_instance_via_dev_mode
|
321
409
|
session["appInstance"] = ZuoraConnect.configuration.dev_mode_appinstance
|
322
410
|
user = ZuoraConnect.configuration.dev_mode_user
|
@@ -340,24 +428,6 @@ module ZuoraConnect
|
|
340
428
|
end
|
341
429
|
session["#{@appinstance.id}::admin"] = ZuoraConnect.configuration.dev_mode_admin
|
342
430
|
end
|
343
|
-
|
344
|
-
#API ONLY
|
345
|
-
def check_instance
|
346
|
-
if defined?(@appinstance) && @appinstance.present?
|
347
|
-
if @appinstance.new_session_for_api_requests(:params => params)
|
348
|
-
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
349
|
-
end
|
350
|
-
Thread.current[:appinstance] = @appinstance
|
351
|
-
PaperTrail.whodunnit = "API User" if defined?(PaperTrail)
|
352
|
-
ElasticAPM.set_user("API User") if defined?(ElasticAPM) && ElasticAPM.running?
|
353
|
-
return true
|
354
|
-
else
|
355
|
-
response.set_header('WWW-Authenticate', "Basic realm=\"Application\"")
|
356
|
-
#render json: {"status": 401, "message": "Access Denied"}, status: :unauthorized
|
357
|
-
render html: "HTTP Basic: Access denied.\n", status: :unauthorized
|
358
|
-
render plain: "Access Denied", status: :unauthorized
|
359
|
-
end
|
360
|
-
end
|
361
431
|
end
|
362
432
|
end
|
363
433
|
end
|