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.
@@ -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, :app_access_permissions
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
- else #if request.headers.fetch("Authorization", "").include?("Basic ")
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
- # else
54
- # check_instance
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 request.headers['ZuoraCurrentEntity'].present?
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
- #Identity blank or current entity different
81
- if (session["ZuoraCurrentIdentity"].blank? || session["ZuoraCurrentEntity"] != zuora_entity_id)
82
- begin
83
- identity, response = zuora_client.rest_call(url: zuora_client.rest_endpoint("identity"))
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
- raise ZuoraConnect::Exceptions::Error.new("Header entity id, '#{zuora_entity_id}' does not match identity call entity id, '#{identity['entityId']}'.") if zuora_entity_id != identity['entityId']
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
- #Find matching app instances.
96
- if zuora_instance_id.present?
97
- 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)
98
- else
99
- #if app_instance_ids is present then permissions still controlled by connect
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
- 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)
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
- zuora_user_id = cookies['Zuora-User-Id'] || session["ZuoraCurrentIdentity"]['userId']
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
- #One deployed instance
122
- if appinstances.size == 1
123
- ZuoraConnect.logger.debug("Instance is #{appinstances.to_h.keys.first}")
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
- #Add user/update
126
- @user = ZuoraConnect::ZuoraUser.where(:zuora_user_id => zuora_user_id).first
127
- if @user.present?
128
- ZuoraConnect.logger.debug("Current zuora user #{zuora_user_id}")
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
- #If user has has access to application
144
- if @user.app_permissions['access'].to_bool || !ZuoraConnect.configuration.app_access_permissions
145
- session["appInstance"] = appinstances.to_h.keys.first
146
- else
147
- Thread.current[:appinstance] = nil
148
- session["appInstance"] = nil
149
- admin_users = ZuoraConnect::ZuoraUser.select("zuora_identity_response #>> '{#{zuora_entity_id},username}' as username").where("zuora_identity_response #>> :selector = 'ADMIN' ", :selector => "{#{zuora_entity_id},platformRole}")
150
- render "zuora_connect/static/permission_error", :locals => {:admins => admin_users}
151
- return
152
- end
153
- #We have multiple, user must pick
154
- elsif appinstances.size > 1
155
- ZuoraConnect.logger.debug("User must select instance. #{@names}")
156
- render "zuora_connect/static/launch", :locals => {:names => appinstances.to_h}
157
- return
158
- else
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
- body = {
166
- 'userId' => zuora_user_id,
167
- 'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
168
- 'customAuthorities' => [],
169
- 'additionalInformation' => {
170
- 'description' => 'This user is for workflow application.',
171
- 'name' => 'Workflow API User'
172
- }
173
- }
174
-
175
- 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)}"})
176
-
177
- new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
178
-
179
- client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
180
-
181
- Apartment::Tenant.switch!("public")
182
- next_id = (ZuoraConnect::AppInstance.all.where(:access_token => nil).order(id: :desc).limit(1).pluck(:id).first || 24999999) + 1
183
- begin
184
- Apartment::Tenant.create(next_id.to_s)
185
- rescue Apartment::TenantExists => ex
186
- ZuoraConnect.logger.debug("Tenant Already Exists")
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
- task_data = {
190
- "id": next_id,
191
- "name": client_describe["tenantName"],
192
- "mode": "Collections",
193
- "status": "Running",
194
- "target_login": {
195
- "tenant_type": "Zuora",
196
- "username": session["ZuoraCurrentIdentity"]["username"],
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
- end
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
- setup_instance_via_session
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
- I18n.locale = session["#{@appinstance.id}::user::locale"] ? session["#{@appinstance.id}::user::locale"] : @appinstance.locale
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
- Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
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
- @appinstance = ZuoraConnect::AppInstance.new(:api_token => values[:api_token],:id => values["appInstance"].to_i, :access_token => values["access_token"].blank? ? values["user"] : values["access_token"], :token => values["refresh_token"] , :refresh_token => values["refresh_token"].blank? ? values["key"] : values["refresh_token"], :oauth_expires_at => values["expires"])
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
- @appinstance.access_token = values["access_token"] if !values["access_token"].blank? && @appinstance.access_token != values["access_token"]
301
- @appinstance.refresh_token = values["refresh_token"] if !values["refresh_token"].blank? && @appinstance.refresh_token != values["refresh_token"]
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 mistmatch. Possible tampering")
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