zuora_connect 0 → 3.2.11
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/MIT-LICENSE +1 -1
- data/README.md +219 -0
- data/Rakefile +1 -1
- data/app/assets/javascripts/hallway_wrapper/after.js +22 -3
- data/app/controllers/concerns/zuora_connect/authenticate.rb +39 -0
- data/app/controllers/zuora_connect/api/v1/app_instance_controller.rb +5 -0
- data/app/controllers/zuora_connect/application_controller.rb +37 -2
- data/app/controllers/zuora_connect/static_controller.rb +142 -27
- data/app/helpers/zuora_connect/LDAP/adapter.rb +16 -0
- data/app/helpers/zuora_connect/LDAP/connection.rb +123 -0
- data/app/helpers/zuora_connect/application_helper.rb +10 -0
- data/app/models/concerns/zuora_connect/auditable.rb +29 -0
- data/app/models/zuora_connect/app_instance_base.rb +652 -180
- data/app/models/zuora_connect/login.rb +24 -11
- data/app/models/zuora_connect/telegraf.rb +18 -38
- data/app/models/zuora_connect/zuora_user.rb +35 -0
- data/app/views/sql/refresh_aggregate_table.txt +12 -10
- data/app/views/zuora_connect/application/ldap_login.html.erb +195 -0
- data/app/views/zuora_connect/static/error_handled.html.erb +76 -0
- data/app/views/zuora_connect/static/error_handled.js.erb +1 -0
- data/app/views/zuora_connect/static/error_unhandled.erb +85 -0
- data/app/views/zuora_connect/static/error_unhandled.js.erb +1 -0
- data/app/views/zuora_connect/static/launch.html.erb +71 -76
- data/config/initializers/object_method_hooks.rb +2 -2
- data/config/initializers/patches.rb +9 -0
- data/config/initializers/postgresql_adapter.rb +119 -1
- data/config/initializers/prometheus.rb +57 -23
- data/config/initializers/redis.rb +52 -5
- data/config/initializers/resque.rb +5 -1
- data/config/initializers/unicorn.rb +30 -2
- data/config/initializers/zuora_observability.rb +24 -0
- data/config/routes.rb +8 -3
- data/db/migrate/20100718151733_create_connect_app_instances.rb +1 -1
- data/db/migrate/20101024162319_add_tokens_to_app_instance.rb +1 -1
- data/db/migrate/20101024220705_add_token_to_app_instance.rb +1 -1
- data/db/migrate/20110131211919_add_sessions_table.rb +1 -1
- data/db/migrate/20110411200303_add_expiration_to_app_instance.rb +1 -1
- data/db/migrate/20110413191512_add_new_api_token.rb +1 -1
- data/db/migrate/20110503003602_add_catalog_data_to_app_instance.rb +1 -1
- data/db/migrate/20110503003603_add_catalog_mappings_to_app_instance.rb +1 -1
- data/db/migrate/20110503003604_catalog_default.rb +1 -1
- data/db/migrate/20180301052853_add_catalog_attempted_at.rb +1 -1
- data/db/migrate/20181206162339_add_fields_to_instance.rb +1 -1
- data/db/migrate/20190520232221_add_zuora_user_table_and_alter_app_instance_id_table.rb +18 -0
- data/db/migrate/20190520232222_add_unique_index.rb +6 -0
- data/db/migrate/20190520232223_add_provisioning_fields.rb +6 -0
- data/db/migrate/20190520232224_add_environment_fields.rb +16 -0
- data/lib/metrics/net.rb +3 -3
- data/lib/middleware/json_parse_errors.rb +33 -0
- data/lib/middleware/metrics_middleware.rb +62 -68
- data/lib/middleware/request_id_middleware.rb +17 -0
- data/lib/resque/dynamic_queues.rb +35 -13
- data/lib/resque/plugins/app_instance_job.rb +63 -0
- data/lib/resque/plugins/custom_logger.rb +12 -27
- data/lib/tasks/zuora_connect_tasks.rake +0 -5
- data/lib/zuora_connect/configuration.rb +8 -4
- data/lib/zuora_connect/controllers/helpers.rb +640 -189
- data/lib/zuora_connect/engine.rb +12 -9
- data/lib/zuora_connect/exceptions.rb +18 -2
- data/lib/zuora_connect/middleware/hallway.rb +34 -0
- data/lib/zuora_connect/railtie.rb +16 -39
- data/lib/zuora_connect/version.rb +3 -1
- data/lib/zuora_connect.rb +69 -5
- metadata +146 -126
- data/app/views/zuora_connect/static/invalid_app_instance_error.html.erb +0 -65
- data/app/views/zuora_connect/static/invalid_launch_request.html +0 -65
- data/app/views/zuora_connect/static/session_error.html.erb +0 -63
- data/config/initializers/elastic_apm.rb +0 -25
- data/lib/zuora_connect/views/helpers.rb +0 -9
- data/test/controllers/zuora_connect/api/v1/app_instance_controller_test.rb +0 -13
- data/test/dummy/README.rdoc +0 -28
- data/test/dummy/Rakefile +0 -6
- data/test/dummy/app/assets/javascripts/application.js +0 -13
- data/test/dummy/app/assets/stylesheets/application.css +0 -15
- data/test/dummy/app/controllers/application_controller.rb +0 -5
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/views/layouts/application.html.erb +0 -14
- data/test/dummy/bin/bundle +0 -3
- data/test/dummy/bin/rails +0 -4
- data/test/dummy/bin/rake +0 -4
- data/test/dummy/bin/setup +0 -29
- data/test/dummy/config/application.rb +0 -26
- data/test/dummy/config/boot.rb +0 -5
- data/test/dummy/config/database.yml +0 -25
- data/test/dummy/config/environment.rb +0 -5
- data/test/dummy/config/environments/development.rb +0 -41
- data/test/dummy/config/environments/production.rb +0 -79
- data/test/dummy/config/environments/test.rb +0 -42
- data/test/dummy/config/initializers/assets.rb +0 -11
- data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
- data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/test/dummy/config/initializers/inflections.rb +0 -16
- data/test/dummy/config/initializers/mime_types.rb +0 -4
- data/test/dummy/config/initializers/session_store.rb +0 -3
- data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/test/dummy/config/locales/en.yml +0 -23
- data/test/dummy/config/routes.rb +0 -4
- data/test/dummy/config/secrets.yml +0 -22
- data/test/dummy/config.ru +0 -4
- data/test/dummy/public/404.html +0 -67
- data/test/dummy/public/422.html +0 -67
- data/test/dummy/public/500.html +0 -66
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/zuora_connect/app_instances.yml +0 -11
- data/test/integration/navigation_test.rb +0 -8
- data/test/lib/generators/zuora_connect/datatable_generator_test.rb +0 -16
- data/test/models/zuora_connect/app_instance_test.rb +0 -9
- data/test/test_helper.rb +0 -21
- data/test/zuora_connect_test.rb +0 -7
|
@@ -5,147 +5,190 @@ module ZuoraConnect
|
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
7
|
def authenticate_app_api_request
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
ElasticAPM.set_tag(:trace_id, request.uuid) if defined?(ElasticAPM)
|
|
12
|
-
|
|
13
|
-
start_time = Time.now
|
|
14
|
-
if request.headers["API-Token"].present?
|
|
15
|
-
@appinstance = ZuoraConnect::AppInstance.where(:api_token => request.headers["API-Token"]).first
|
|
16
|
-
Rails.logger.debug("[#{@appinstance.id}] API REQUEST - API token") if @appinstance.present?
|
|
17
|
-
check_instance
|
|
18
|
-
else
|
|
19
|
-
authenticate_or_request_with_http_basic do |username, password|
|
|
20
|
-
@appinstance = ZuoraConnect::AppInstance.where(:token => password).first
|
|
21
|
-
@appinstance ||= ZuoraConnect::AppInstance.where(:api_token => password).first
|
|
22
|
-
Rails.logger.debug("[#{@appinstance.id}] API REQUEST - Basic Auth") if @appinstance.present?
|
|
23
|
-
check_instance
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
if @appinstance.present?
|
|
27
|
-
Rails.logger.debug("[#{@appinstance.id}] Authenticate App API Request Completed In - #{(Time.now - start_time).round(2)}s")
|
|
28
|
-
end
|
|
29
|
-
end
|
|
8
|
+
ZuoraConnect::AppInstance.read_master_db do
|
|
9
|
+
#Skip session for api requests
|
|
10
|
+
request.session_options[:skip] = true
|
|
30
11
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
matches[0].split("?").first == ENV["DEIS_APP"]
|
|
12
|
+
Thread.current[:appinstance] = nil
|
|
13
|
+
if ZuoraConnect.logger.is_a?(Ougai::Logger); ZuoraConnect.logger.with_fields = {}; end
|
|
14
|
+
if Rails.logger.is_a?(Ougai::Logger); Rails.logger.with_fields = {}; end
|
|
15
|
+
if defined?(ElasticAPM) && ElasticAPM.running?
|
|
16
|
+
if ElasticAPM.respond_to?(:set_label)
|
|
17
|
+
ElasticAPM.set_label(:trace_id, request.uuid) if defined?(ElasticAPM) && ElasticAPM.running?
|
|
18
|
+
else
|
|
19
|
+
ElasticAPM.set_label(:trace_id, request.uuid) if defined?(ElasticAPM) && ElasticAPM.running?
|
|
40
20
|
end
|
|
41
21
|
end
|
|
42
22
|
|
|
43
|
-
|
|
44
|
-
return app[0]
|
|
45
|
-
else
|
|
46
|
-
return session[params[:app_instance_ids]]
|
|
47
|
-
end
|
|
48
|
-
end
|
|
23
|
+
ZuoraConnect::ZuoraUser.current_user_id = request.headers["Zuora-User-Id"]
|
|
49
24
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
25
|
+
if request.headers["API-Token"].present?
|
|
26
|
+
@appinstance = ZuoraConnect::AppInstance.find_by(:api_token => request.headers["API-Token"])
|
|
27
|
+
ZuoraConnect.logger.debug("API REQUEST - API token") if @appinstance.present?
|
|
28
|
+
check_instance
|
|
29
|
+
elsif ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(request.headers.fetch("HOST", nil)) && request.headers['zuora-host'].present?
|
|
30
|
+
zuora_host, zuora_entity_id, zuora_instance_id = [request.headers['zuora-host'], (request.headers['zuora-entity-ids'] || "").gsub('-',''), request.headers['zuora-instance-id']]
|
|
31
|
+
zuora_host_mapping = {'origin-gateway.sbx.auw2.zuora.com' => 'rest.apisandbox.zuora.com', 'origin-gateway.prod.auw2.zuora.com' => 'rest.zuora.com'}
|
|
32
|
+
zuora_host = zuora_host_mapping[zuora_host] if zuora_host_mapping.keys.include?(zuora_host)
|
|
53
33
|
|
|
54
|
-
|
|
55
|
-
|
|
34
|
+
#Validate entity-ids present
|
|
35
|
+
if zuora_entity_id.blank?
|
|
36
|
+
render json: {"status": 401, "message": "zuora-entity-ids header was not supplied."}, status: :unauthorized
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
#Select with instance id if present. Used where mulitple deployments are done.
|
|
40
|
+
if zuora_instance_id.present?
|
|
41
|
+
appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host AND id = :id", entities: [zuora_entity_id], host: zuora_host, id: zuora_instance_id.to_i)
|
|
42
|
+
else
|
|
43
|
+
appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host", entities: [zuora_entity_id], host: zuora_host)
|
|
44
|
+
end
|
|
56
45
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
if appinstances.size == 0
|
|
47
|
+
render json: {"status": 404, "message": "Missing mapping or no deployment for '#{zuora_host}-#{zuora_entity_id}' ."}, status: 404
|
|
48
|
+
return
|
|
49
|
+
elsif appinstances.size > 1
|
|
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
|
|
51
|
+
return
|
|
52
|
+
else
|
|
53
|
+
@appinstance = appinstances.first
|
|
54
|
+
check_instance
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
elsif request.headers.fetch("Authorization", "").include?("Basic ")
|
|
58
|
+
authenticate_or_request_with_http_basic do |username, password|
|
|
59
|
+
@appinstance = ZuoraConnect::AppInstance.find_by(:token => password)
|
|
60
|
+
@appinstance ||= ZuoraConnect::AppInstance.find_by(:api_token => password)
|
|
61
|
+
ZuoraConnect.logger.debug("API REQUEST - Basic Auth") if @appinstance.present?
|
|
62
|
+
check_instance
|
|
63
63
|
end
|
|
64
|
-
render "zuora_connect/static/launch"
|
|
65
64
|
else
|
|
66
|
-
|
|
65
|
+
check_instance
|
|
67
66
|
end
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
|
|
68
|
+
@zuora_user = ZuoraConnect::ZuoraUser.find_by(zuora_user_id: ZuoraConnect::ZuoraUser.current_user_id)
|
|
69
|
+
zuora_org_ids = request.headers["Zuora-Org-Ids"]
|
|
70
|
+
ZuoraConnect::ZuoraUser.current_org_ids = []
|
|
71
|
+
ZuoraConnect::ZuoraUser.current_org_ids = zuora_org_ids.split(',') if zuora_org_ids
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
rescue ZuoraConnect::Exceptions::ConnectCommunicationError => ex
|
|
75
|
+
render json: {"status": 400, "message": ex.message}, status: 400
|
|
76
|
+
return
|
|
77
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIInternalServerError => ex
|
|
78
|
+
render json: {"status": 500, "message": ex.message}, status: 500
|
|
79
|
+
return
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
#API ONLY
|
|
83
|
+
def check_instance
|
|
84
|
+
if defined?(@appinstance) && @appinstance.present?
|
|
85
|
+
if @appinstance.new_session_for_api_requests(:params => params)
|
|
86
|
+
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
|
87
|
+
end
|
|
88
|
+
Thread.current[:appinstance] = @appinstance
|
|
89
|
+
PaperTrail.whodunnit = "API User" if defined?(PaperTrail)
|
|
90
|
+
ElasticAPM.set_user("API User") if defined?(ElasticAPM) && ElasticAPM.running?
|
|
91
|
+
return true
|
|
92
|
+
else
|
|
93
|
+
response.set_header('WWW-Authenticate', "Basic realm=\"Application\"")
|
|
94
|
+
render json: {"status": 401, "message": "Access Denied"}, status: :unauthorized
|
|
95
|
+
return false
|
|
71
96
|
end
|
|
72
97
|
end
|
|
73
98
|
|
|
74
99
|
def authenticate_connect_app_request
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if
|
|
81
|
-
|
|
82
|
-
instances = JSON.parse(Base64.urlsafe_decode64(CGI.parse(URI.parse(session[params[:app_instance_ids]]["url"]).query)["app_instance_ids"][0]))
|
|
83
|
-
if instances.include?(app_instance_ids[0])
|
|
84
|
-
@appinstance = ZuoraConnect::AppInstance.find(app_instance_ids[0])
|
|
85
|
-
@appinstance.new_session(session: {})
|
|
86
|
-
@appinstance.cache_app_instance
|
|
87
|
-
session["appInstance"] = app_instance_ids[0]
|
|
88
|
-
else
|
|
89
|
-
Rails.logger.fatal("Launch Error: Param Instance didnt match session data")
|
|
90
|
-
render "zuora_connect/static/invalid_launch_request"
|
|
91
|
-
return
|
|
92
|
-
end
|
|
100
|
+
ZuoraConnect::AppInstance.read_master_db do
|
|
101
|
+
Thread.current[:appinstance] = nil
|
|
102
|
+
if ZuoraConnect.logger.is_a?(Ougai::Logger); ZuoraConnect.logger.with_fields = {}; end
|
|
103
|
+
if Rails.logger.is_a?(Ougai::Logger); Rails.logger.with_fields = {}; end
|
|
104
|
+
if defined?(ElasticAPM) && ElasticAPM.running?
|
|
105
|
+
if ElasticAPM.respond_to?(:set_label)
|
|
106
|
+
ElasticAPM.set_label(:trace_id, request.uuid)
|
|
93
107
|
else
|
|
94
|
-
|
|
95
|
-
return
|
|
108
|
+
ElasticAPM.set_label(:trace_id, request.uuid)
|
|
96
109
|
end
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
if ZuoraConnect.configuration.mode == "Production"
|
|
113
|
+
setup_instance_via_prod_mode
|
|
114
|
+
else
|
|
115
|
+
setup_instance_via_dev_mode
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
return if performed?
|
|
119
|
+
|
|
120
|
+
if !defined?(@appinstance) || @appinstance.blank?
|
|
121
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
122
|
+
:title => "Application state could not be found.",
|
|
123
|
+
:message => "Please relaunch application."
|
|
124
|
+
}, :layout => false
|
|
100
125
|
return
|
|
101
126
|
end
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
@appinstance = ZuoraConnect::AppInstance.find(params[:app_instance_id].to_i)
|
|
108
|
-
@appinstance.new_session(session: {})
|
|
109
|
-
@appinstance.cache_app_instance
|
|
110
|
-
session["appInstance"] = params[:app_instance_id].to_i
|
|
111
|
-
else
|
|
112
|
-
render "zuora_connect/static/invalid_launch_request"
|
|
113
|
-
return
|
|
127
|
+
#Call .data_lookup with the current session to retrieve session. In some cases session may be stored/cache in redis
|
|
128
|
+
#so data lookup provides a model method that can be overriden per app.
|
|
129
|
+
if params[:controller] != 'zuora_connect/api/v1/app_instance' && params[:action] != 'drop'
|
|
130
|
+
if @appinstance.new_session_for_ui_requests(:params => params)
|
|
131
|
+
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
|
114
132
|
end
|
|
115
|
-
rescue => ex
|
|
116
|
-
Rails.logger.fatal("Launch Error: #{ex.message}")
|
|
117
|
-
render "zuora_connect/static/invalid_launch_request"
|
|
118
|
-
return
|
|
119
133
|
end
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
setup_instance_via_data
|
|
125
|
-
else
|
|
126
|
-
setup_instance_via_session
|
|
134
|
+
|
|
135
|
+
if session["#{@appinstance.id}::user::email"].present?
|
|
136
|
+
ElasticAPM.set_user(session["#{@appinstance.id}::user::email"]) if defined?(ElasticAPM) && ElasticAPM.running?
|
|
137
|
+
PaperTrail.whodunnit = session["#{@appinstance.id}::user::email"] if defined?(PaperTrail)
|
|
127
138
|
end
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
|
|
140
|
+
locale = (session["#{@appinstance.id}::user::locale"] || "").gsub("_", "-")
|
|
141
|
+
begin
|
|
142
|
+
I18n.locale = locale.present? ? locale : @appinstance.locale
|
|
143
|
+
rescue I18n::InvalidLocale => ex
|
|
144
|
+
if locale.include?("-")
|
|
145
|
+
locale = locale.split("-").first
|
|
146
|
+
retry
|
|
147
|
+
elsif locale != session["#{@appinstance.id}::user::language"]
|
|
148
|
+
locale = session["#{@appinstance.id}::user::language"]
|
|
149
|
+
retry
|
|
150
|
+
end
|
|
151
|
+
ZuoraConnect.logger.error(ex) if !ZuoraConnect::AppInstance::IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
|
|
152
|
+
end
|
|
153
|
+
if @appinstance.user_timezone.blank?
|
|
154
|
+
@appinstance.set_timezone(timezone: session["#{@appinstance.id}::user::timezone"], type: :default)
|
|
136
155
|
end
|
|
137
156
|
end
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
157
|
+
rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
|
|
158
|
+
id = @appinstance.id
|
|
159
|
+
ZuoraConnect::AppInstance.destroy(id)
|
|
160
|
+
Apartment::Tenant.drop(id)
|
|
161
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
162
|
+
:title => "Application Setup Error",
|
|
163
|
+
:message => "Application cannot be run using Zuora Session. Delete old application \
|
|
164
|
+
deployment and create new with Zuora Basic or OAuth credentials."
|
|
165
|
+
}, :layout => false
|
|
166
|
+
return
|
|
167
|
+
rescue ZuoraConnect::Exceptions::AccessDenied => ex
|
|
168
|
+
respond_to do |format|
|
|
169
|
+
format.html {
|
|
170
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
171
|
+
:title => "Application State Error",
|
|
172
|
+
:message => ex.message
|
|
173
|
+
}, status: 401, layout: false
|
|
174
|
+
}
|
|
175
|
+
format.js {
|
|
176
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
177
|
+
:title => "Application State Error",
|
|
178
|
+
:message => ex.message
|
|
179
|
+
}, status: 401, layout: false
|
|
180
|
+
}
|
|
181
|
+
format.json { render json: {'errors' => ex.message}, status: 401 }
|
|
182
|
+
format.all { render json: ex.message, status: 401 }
|
|
141
183
|
end
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
184
|
+
return
|
|
185
|
+
rescue => ex
|
|
186
|
+
ZuoraConnect.logger.error("UI Authorization Error", ex)
|
|
187
|
+
respond_to do |format|
|
|
188
|
+
format.html { render 'zuora_connect/static/error_unhandled', :locals => {:exception => ex, :skip_exception => true}, status: 500, layout: false }
|
|
189
|
+
format.js { render 'zuora_connect/static/error_unhandled', :locals => {:exception => ex, :skip_exception => true}, status: 500, layout: false}
|
|
146
190
|
end
|
|
147
|
-
|
|
148
|
-
Rails.logger.debug("[#{@appinstance.blank? ? "N/A" : @appinstance.id}] Authenticate App Request Completed In - #{(Time.now - start_time).round(2)}s")
|
|
191
|
+
return
|
|
149
192
|
end
|
|
150
193
|
|
|
151
194
|
def persist_connect_app_session
|
|
@@ -158,103 +201,511 @@ module ZuoraConnect
|
|
|
158
201
|
end
|
|
159
202
|
end
|
|
160
203
|
|
|
161
|
-
def check_connect_admin!
|
|
162
|
-
|
|
204
|
+
def check_connect_admin!(raise_error: false)
|
|
205
|
+
if !(session["#{@appinstance.id}::admin"] || @appinstance.zuora_tenant_ids.include?("9"))
|
|
206
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("User is not an authorized admin for this application") if raise_error
|
|
207
|
+
|
|
208
|
+
respond_to do |format|
|
|
209
|
+
format.html {
|
|
210
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
211
|
+
:title => "Unauthorized",
|
|
212
|
+
:message => "User is not an authorized admin for this application"
|
|
213
|
+
}, status: 401, :layout => false
|
|
214
|
+
}
|
|
215
|
+
format.js {
|
|
216
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
217
|
+
:title => "Unauthorized",
|
|
218
|
+
:message => "User is not an authorized admin for this application"
|
|
219
|
+
}, status: 401, :layout => false
|
|
220
|
+
}
|
|
221
|
+
format.json { render json: {'errors' => ex.message}, status: 401 }
|
|
222
|
+
format.all { render json: ex.message, status: 401 }
|
|
223
|
+
end
|
|
224
|
+
return
|
|
225
|
+
end
|
|
163
226
|
end
|
|
164
227
|
|
|
165
228
|
def check_connect_admin
|
|
166
229
|
return session["#{@appinstance.id}::admin"]
|
|
167
230
|
end
|
|
168
231
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
232
|
+
def zuora_user
|
|
233
|
+
return @zuora_user
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def hallway_integration?
|
|
237
|
+
return (request.headers['ZuoraCurrentEntity'].present? || cookies['ZuoraCurrentEntity'].present?)
|
|
238
|
+
end
|
|
239
|
+
def create_new_instance
|
|
240
|
+
ZuoraConnect::AppInstance.read_master_db do
|
|
241
|
+
Thread.current[:appinstance] = nil
|
|
242
|
+
ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
|
|
243
|
+
Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
|
|
244
|
+
|
|
245
|
+
if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
|
|
246
|
+
ElasticAPM.set_label(:trace_id, request.uuid)
|
|
177
247
|
end
|
|
178
|
-
end
|
|
179
|
-
session["#{values["appInstance"]}::destroy"] = values["destroy"]
|
|
180
|
-
session["appInstance"] = values["appInstance"]
|
|
181
|
-
if values["current_user"]
|
|
182
|
-
session["#{values["appInstance"]}::admin"] = values["current_user"]["admin"] ? values["current_user"]["admin"] : false
|
|
183
|
-
session["#{values["appInstance"]}::user::timezone"] = values["current_user"]["timezone"]
|
|
184
|
-
session["#{values["appInstance"]}::user::locale"] = values["current_user"]["locale"]
|
|
185
|
-
session["#{values["appInstance"]}::user::email"] = values["current_user"]["email"]
|
|
186
|
-
end
|
|
187
248
|
|
|
188
|
-
|
|
249
|
+
zuora_host = request.headers['zuora-host']
|
|
250
|
+
zuora_entity_id = (request.headers['zuora-entity-ids'] || '').gsub(
|
|
251
|
+
'-',
|
|
252
|
+
''
|
|
253
|
+
).split(',').first
|
|
189
254
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
255
|
+
# Validate host present
|
|
256
|
+
if zuora_host.blank?
|
|
257
|
+
render json: {
|
|
258
|
+
status: 401,
|
|
259
|
+
message: 'zuora-host header was not supplied.'
|
|
260
|
+
}, status: :unauthorized
|
|
261
|
+
return
|
|
197
262
|
end
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
263
|
+
|
|
264
|
+
# Validate entity-ids present
|
|
265
|
+
if zuora_entity_id.blank?
|
|
266
|
+
render json: {
|
|
267
|
+
status: 401,
|
|
268
|
+
message: 'zuora-entity-ids header was not supplied.'
|
|
269
|
+
}, status: :unauthorized
|
|
270
|
+
return
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
rest_domain = ZuoraAPI::Login.new(url: "https://#{zuora_host}").rest_domain
|
|
274
|
+
app_instance_id = ZuoraConnect::AppInstance.where(
|
|
275
|
+
'zuora_entity_ids ?& array[:entities] AND zuora_domain = :host',
|
|
276
|
+
entities: [zuora_entity_id],
|
|
277
|
+
host: rest_domain
|
|
278
|
+
).pluck(:id).first
|
|
279
|
+
|
|
280
|
+
if app_instance_id.present?
|
|
281
|
+
render json: {
|
|
282
|
+
status: 409,
|
|
283
|
+
message: 'Instance already exists.',
|
|
284
|
+
app_instance_id: app_instance_id
|
|
285
|
+
}, status: 409
|
|
207
286
|
else
|
|
208
|
-
|
|
287
|
+
Apartment::Tenant.switch!("public")
|
|
288
|
+
retry_count = 3
|
|
289
|
+
begin
|
|
290
|
+
@appinstance = new_instance(
|
|
291
|
+
next_instance_id,
|
|
292
|
+
zuora_entity_id,
|
|
293
|
+
rest_domain,
|
|
294
|
+
tenant_id: request.headers['zuora-tenant-id'],
|
|
295
|
+
retry_count: retry_count
|
|
296
|
+
)
|
|
297
|
+
rescue ActiveRecord::RecordNotUnique
|
|
298
|
+
retry if (retry_count -= 1).positive?
|
|
299
|
+
return
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
app_instance_id = @appinstance.id
|
|
209
303
|
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
304
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
305
|
+
begin
|
|
306
|
+
Apartment::Tenant.switch!('public')
|
|
307
|
+
Apartment::Tenant.create(app_instance_id.to_s)
|
|
308
|
+
rescue Apartment::TenantExists
|
|
309
|
+
ZuoraConnect.logger.debug('Tenant Already Exists')
|
|
310
|
+
end
|
|
218
311
|
end
|
|
219
312
|
end
|
|
220
313
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
314
|
+
private
|
|
315
|
+
def setup_instance_via_prod_mode
|
|
316
|
+
zuora_entity_id = request.headers['ZuoraCurrentEntity'] || cookies['ZuoraCurrentEntity']
|
|
317
|
+
ZuoraConnect::ZuoraUser.current_user_id = '3'
|
|
318
|
+
|
|
319
|
+
if zuora_entity_id.present?
|
|
320
|
+
zuora_tenant_id = cookies['Zuora-Tenant-Id']
|
|
321
|
+
zuora_user_id = cookies['Zuora-User-Id']
|
|
322
|
+
zuora_host = request.headers['HTTP_X_FORWARDED_HOST'] || request.headers['HTTP_ZUORA_HOST'] || 'apisandbox.zuora.com'
|
|
323
|
+
|
|
324
|
+
zuora_details = {'host' => zuora_host, 'user_id' => zuora_user_id, 'tenant_id' => zuora_tenant_id, 'entity_id' => zuora_entity_id}
|
|
325
|
+
auth_headers = {}
|
|
326
|
+
#Do we need to refresh session identity
|
|
327
|
+
if request.headers["Zuora-Auth-Token"].present?
|
|
328
|
+
zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", bearer_token: request.headers["Zuora-Auth-Token"], entity_id: zuora_entity_id, oauth_session_expires_at: Time.now + 5.minutes )
|
|
329
|
+
elsif cookies['ZSession'].present?
|
|
330
|
+
zuora_client = ZuoraAPI::Basic.new(url: "https://#{zuora_host}", session: cookies['ZSession'], entity_id: zuora_entity_id)
|
|
331
|
+
auth_headers.merge!({'Authorization' => "ZSession-a3N2w #{zuora_client.get_session(prefix: false, auth_type: :basic)}"})
|
|
332
|
+
else
|
|
333
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
334
|
+
:title => "Missing Authorization Token",
|
|
335
|
+
:message => "Zuora 'Zuora-Auth-Token' header and 'ZSession' cookie not present."
|
|
336
|
+
}, :layout => false
|
|
337
|
+
return
|
|
338
|
+
end
|
|
339
|
+
|
|
229
340
|
begin
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
341
|
+
zuora_instance_id = params[:sidebar_launch].to_s.to_bool ? nil : (params[:app_instance_id] || session["appInstance"])
|
|
342
|
+
|
|
343
|
+
#Identity blank or current entity different
|
|
344
|
+
different_zsession = session["ZSession"] != cookies['ZSession']
|
|
345
|
+
missmatched_entity = session["ZuoraCurrentEntity"] != zuora_entity_id
|
|
346
|
+
missing_identity = session["ZuoraCurrentIdentity"].blank?
|
|
347
|
+
|
|
348
|
+
if (missing_identity || missmatched_entity || different_zsession)
|
|
349
|
+
zuora_details.merge!({'identity' => {'different_zsession' => different_zsession, 'missing_identity' => missing_identity, 'missmatched_entity' => missmatched_entity}})
|
|
350
|
+
identity, response = zuora_client.rest_call(
|
|
351
|
+
url: zuora_client.rest_endpoint("identity"),
|
|
352
|
+
zuora_track_id: ZuoraConnect::RequestIdMiddleware.zuora_request_id
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
if zuora_entity_id != identity['entityId']
|
|
356
|
+
if zuora_tenant_id.to_s == "10548"
|
|
357
|
+
session.clear
|
|
358
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
359
|
+
:title => "Security Testing",
|
|
360
|
+
:message => "Ya we know it you"
|
|
361
|
+
}, :layout => false
|
|
362
|
+
return
|
|
363
|
+
else
|
|
364
|
+
raise ZuoraConnect::Exceptions::Error.new("Header entity id does not match identity call entity id.")
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
##
|
|
369
|
+
# If the ZSession was refreshed, but it's still the same user and they aren't launching from the side bar,
|
|
370
|
+
# we don't need to continue
|
|
371
|
+
is_different_user = identity.slice("entityId", "tenantId", "userId", "userProfileId") != (session["ZuoraCurrentIdentity"] || {}).slice("entityId", "tenantId", "userId", "userProfileId")
|
|
372
|
+
zuora_details["identity"]["entityId"] = identity['entityId']
|
|
373
|
+
session["ZuoraCurrentIdentity"] = identity
|
|
374
|
+
session["ZuoraCurrentEntity"] = identity['entityId']
|
|
375
|
+
session["ZSession"] = cookies['ZSession']
|
|
376
|
+
if is_different_user || params[:sidebar_launch].to_s.to_bool
|
|
377
|
+
zuora_instance_id = nil
|
|
378
|
+
ZuoraConnect.logger.debug("UI Authorization", zuora: zuora_details)
|
|
379
|
+
client_describe, response = zuora_client.rest_call(
|
|
380
|
+
url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''),
|
|
381
|
+
session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
|
|
382
|
+
headers: auth_headers,
|
|
383
|
+
zuora_track_id: ZuoraConnect::RequestIdMiddleware.zuora_request_id
|
|
384
|
+
)
|
|
385
|
+
session["ZuoraCurrentUserInfo"] = client_describe
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
if zuora_instance_id.present?
|
|
390
|
+
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)
|
|
391
|
+
else
|
|
392
|
+
#if app_instance_ids is present then permissions still controlled by connect
|
|
393
|
+
if params[:app_instance_ids].present?
|
|
394
|
+
navbar, response = zuora_client.rest_call(
|
|
395
|
+
url: zuora_client.rest_endpoint("navigation"),
|
|
396
|
+
zuora_track_id: ZuoraConnect::RequestIdMiddleware.zuora_request_id
|
|
397
|
+
)
|
|
398
|
+
urls = navbar['menus'].map {|x| x['url']}
|
|
399
|
+
app_env = ENV["DEIS_APP"] || "xyz123"
|
|
400
|
+
url = urls.compact.select {|url| File.basename(url).start_with?(app_env + '?')}.first
|
|
401
|
+
if url.blank?
|
|
402
|
+
if navbar['menus'].map {|x| x['label']}.include?('Link Connect Account')
|
|
403
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
404
|
+
:title => "Link Account",
|
|
405
|
+
:message => "Link Connect account to gain access to application."
|
|
406
|
+
}, :layout => false
|
|
407
|
+
return
|
|
408
|
+
end
|
|
409
|
+
raise ZuoraConnect::Exceptions::APIError.new(message: "#{app_env} navbar url was blank", response: response)
|
|
410
|
+
else
|
|
411
|
+
query_params = CGI.parse(URI.parse(url).query)
|
|
412
|
+
app_instance_ids = query_params["app_instance_ids"][0]
|
|
413
|
+
if app_instance_ids.present?
|
|
414
|
+
begin
|
|
415
|
+
task_ids = JSON.parse(Base64.urlsafe_decode64(app_instance_ids))
|
|
416
|
+
|
|
417
|
+
appinstances = ZuoraConnect::AppInstance.where(:id => task_ids).pluck(:id, :name)
|
|
418
|
+
rescue => ex
|
|
419
|
+
raise ZuoraConnect::Exceptions::APIError.new(message: "Failure in parsing the navbar urls.", response: response)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
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)
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
zuora_user_id = cookies['Zuora-User-Id'] || session["ZuoraCurrentIdentity"]['userId'] || request.headers["Zuora-User-Id"]
|
|
428
|
+
|
|
429
|
+
if appinstances.size == 1
|
|
430
|
+
ZuoraConnect.logger.debug("Instance is #{appinstances.to_h.keys.first}")
|
|
431
|
+
@appinstance = ZuoraConnect::AppInstance.find(appinstances.to_h.keys.first)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
# One deployed instance with credentials
|
|
435
|
+
if defined?(@appinstance) && !@appinstance['zuora_logins'].nil?
|
|
436
|
+
@zuora_user = ZuoraConnect::ZuoraUser.update_id_response(
|
|
437
|
+
zuora_user_id, zuora_entity_id, session["ZuoraCurrentIdentity"],
|
|
438
|
+
@appinstance,
|
|
439
|
+
session['ZuoraCurrentUserInfo']['permissions']
|
|
440
|
+
)
|
|
441
|
+
@zuora_user.session = session
|
|
442
|
+
ZuoraConnect::ZuoraUser.current_user_id = zuora_user_id
|
|
443
|
+
session["#{@appinstance.id}::user::localUserId"] = @zuora_user.id
|
|
444
|
+
session["#{@appinstance.id}::user::email"] = session['ZuoraCurrentIdentity']["username"]
|
|
445
|
+
session["#{@appinstance.id}::user::timezone"] = session['ZuoraCurrentIdentity']["timeZone"]
|
|
446
|
+
session["#{@appinstance.id}::user::language"] = session['ZuoraCurrentIdentity']["language"]
|
|
447
|
+
session["#{@appinstance.id}::user::locale"] = session['ZuoraCurrentIdentity']["locale"]
|
|
448
|
+
session["appInstance"] = @appinstance.id
|
|
449
|
+
|
|
450
|
+
#We have multiple, user must pick
|
|
451
|
+
elsif appinstances.size > 1
|
|
452
|
+
ZuoraConnect.logger.debug("User must select instance. #{@names}")
|
|
453
|
+
render "zuora_connect/static/launch", :locals => {:names => appinstances.to_h}, :layout => false
|
|
454
|
+
return
|
|
455
|
+
|
|
456
|
+
#We have no deployed instance for this tenant
|
|
457
|
+
else
|
|
458
|
+
if ZuoraConnect.configuration.disable_provisioning
|
|
459
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("Provisioning is suspended")
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
#Ensure user can access oauth creation API
|
|
463
|
+
if !session["ZuoraCurrentUserInfo"]['permissions'].include?("permission.userManagement")
|
|
464
|
+
Thread.current[:appinstance] = nil
|
|
465
|
+
session["appInstance"] = nil
|
|
466
|
+
render "zuora_connect/static/error_handled", :locals => {
|
|
467
|
+
:title => "Application can only complete its initial setup via platform administrator",
|
|
468
|
+
:message => "Please contact admin who has user managment permissions in tenant and have them click and finish setup."
|
|
469
|
+
}, :layout => false
|
|
470
|
+
return
|
|
471
|
+
end
|
|
472
|
+
Apartment::Tenant.switch!("public")
|
|
473
|
+
retry_count = 3
|
|
474
|
+
task_data = {}
|
|
475
|
+
begin
|
|
476
|
+
ActiveRecord::Base.transaction do
|
|
477
|
+
ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
|
|
478
|
+
|
|
479
|
+
unless defined?(@appinstance)
|
|
480
|
+
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)
|
|
481
|
+
|
|
482
|
+
if appinstances.size > 0
|
|
483
|
+
redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}&pos=0"
|
|
484
|
+
return
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
next_id = defined?(@appinstance) ? @appinstance.id : next_instance_id
|
|
489
|
+
if task_data.blank?
|
|
490
|
+
user = (ENV['DEIS_APP'] || "Application").split('-').map(&:capitalize).join(' ')
|
|
491
|
+
body = {
|
|
492
|
+
'userId' => zuora_user_id,
|
|
493
|
+
'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
|
|
494
|
+
'customAuthorities' => [],
|
|
495
|
+
'additionalInformation' => {
|
|
496
|
+
'description' => "This user is for #{user} application.",
|
|
497
|
+
'name' => "#{user} API User #{next_id}"
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
oauth_response, response = zuora_client.rest_call(
|
|
502
|
+
method: :post,
|
|
503
|
+
body: body.to_json,
|
|
504
|
+
url: zuora_client.rest_endpoint("genesis/clients").gsub('v1/', ''),
|
|
505
|
+
session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
|
|
506
|
+
headers: auth_headers,
|
|
507
|
+
zuora_track_id: ZuoraConnect::RequestIdMiddleware.zuora_request_id
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
|
|
511
|
+
if session["ZuoraCurrentUserInfo"].blank?
|
|
512
|
+
client_describe, response = new_zuora_client.rest_call(
|
|
513
|
+
url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''),
|
|
514
|
+
session_type: :bearer,
|
|
515
|
+
zuora_track_id: ZuoraConnect::RequestIdMiddleware.zuora_request_id
|
|
516
|
+
)
|
|
517
|
+
else
|
|
518
|
+
client_describe = session["ZuoraCurrentUserInfo"]
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
available_entities = client_describe["accessibleEntities"].select {|entity| entity['id'] == zuora_entity_id}
|
|
522
|
+
task_data = {
|
|
523
|
+
"id": next_id,
|
|
524
|
+
"name": client_describe["tenantName"],
|
|
525
|
+
"mode": "Collections",
|
|
526
|
+
"status": "Running",
|
|
527
|
+
ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
|
|
528
|
+
"tenant_type": "Zuora",
|
|
529
|
+
"username": session["ZuoraCurrentIdentity"]["username"],
|
|
530
|
+
"url": new_zuora_client.url,
|
|
531
|
+
"status": "Active",
|
|
532
|
+
"oauth_client_id": oauth_response['clientId'],
|
|
533
|
+
"oauth_secret": oauth_response['clientSecret'],
|
|
534
|
+
"authentication_type": "OAUTH",
|
|
535
|
+
"entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
|
|
536
|
+
},
|
|
537
|
+
"tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
|
|
538
|
+
}
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
if defined?(@appinstance)
|
|
542
|
+
@appinstance.zuora_logins = task_data
|
|
543
|
+
@appinstance.save(:validate => false)
|
|
544
|
+
else
|
|
545
|
+
@appinstance = new_instance(
|
|
546
|
+
next_id,
|
|
547
|
+
zuora_entity_id,
|
|
548
|
+
zuora_client.rest_domain,
|
|
549
|
+
task_data: task_data,
|
|
550
|
+
retry_count: retry_count
|
|
551
|
+
)
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
rescue ActiveRecord::RecordNotUnique
|
|
555
|
+
retry if (retry_count -= 1).positive?
|
|
556
|
+
return
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
Apartment::Tenant.switch!("public")
|
|
560
|
+
begin
|
|
561
|
+
Apartment::Tenant.create(@appinstance.id.to_s)
|
|
562
|
+
rescue Apartment::TenantExists => ex
|
|
563
|
+
ZuoraConnect.logger.debug("Tenant Already Exists")
|
|
564
|
+
end
|
|
565
|
+
@appinstance.refresh
|
|
566
|
+
session["appInstance"] = @appinstance.id
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
zuora_org_ids = cookies['Zuora-Org-Ids'] || request.headers['Zuora-Org-Ids']
|
|
570
|
+
ZuoraConnect::ZuoraUser.current_org_ids = []
|
|
571
|
+
ZuoraConnect::ZuoraUser.current_org_ids = zuora_org_ids.split('|') if zuora_org_ids
|
|
572
|
+
|
|
573
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIAuthenticationTypeError => ex
|
|
574
|
+
output_xml, input_xml, response = zuora_client.soap_call(errors: [], z_session: false, zuora_track_id: ZuoraConnect::RequestIdMiddleware.zuora_request_id) do |xml|
|
|
575
|
+
xml['api'].getUserInfo
|
|
576
|
+
end
|
|
577
|
+
final_error = output_xml.xpath('//fns:FaultCode', 'fns' =>'http://fault.api.zuora.com/').text
|
|
578
|
+
session.clear
|
|
579
|
+
if final_error.blank?
|
|
580
|
+
ZuoraConnect.logger.warn("UI Authorization Error", ex, response: { params: response.body })
|
|
581
|
+
elsif final_error != "INVALID_SESSION"
|
|
582
|
+
ZuoraConnect.logger.warn("UI Authorization Error", ex, response: { params: final_error })
|
|
583
|
+
else
|
|
584
|
+
ZuoraConnect.logger.info("UI Authorization Error", ex, response: { params: final_error })
|
|
585
|
+
end
|
|
586
|
+
redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}&pos=1"
|
|
587
|
+
return
|
|
588
|
+
|
|
589
|
+
rescue ZuoraAPI::Exceptions::ZuoraAPIError, Exception => ex
|
|
590
|
+
if ex.message.include?("Referenced User resource(s) not found") && ex.class == ZuoraAPI::Exceptions::ZuoraAPIError
|
|
591
|
+
locals = {title: "Provisioning Error", message: "New tenants need to be provisioned by API Gateway('#{ex.message}'). Please contact support."}
|
|
592
|
+
render "zuora_connect/static/error_handled", locals: locals, status: 200, layout: false
|
|
593
|
+
else
|
|
594
|
+
session.clear
|
|
595
|
+
if defined?(ex.response) && ex.response.present? && defined?(ex.response.body)
|
|
596
|
+
zuora_details.merge!({:error => ex.response.body})
|
|
597
|
+
end
|
|
598
|
+
ZuoraConnect.logger.error("UI Authorization Error", ex, zuora: zuora_details)
|
|
599
|
+
|
|
600
|
+
respond_to do |format|
|
|
601
|
+
format.html {
|
|
602
|
+
render "zuora_connect/static/error_unhandled", locals: {exception: ex, skip_exception: true}, layout: false, status: 500
|
|
603
|
+
}
|
|
604
|
+
format.js {
|
|
605
|
+
render "zuora_connect/static/error_unhandled", locals: {exception: ex, skip_exception: true}, layout: false, status: 500
|
|
606
|
+
}
|
|
607
|
+
end
|
|
608
|
+
end
|
|
609
|
+
return
|
|
610
|
+
end
|
|
611
|
+
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))
|
|
612
|
+
session.clear
|
|
613
|
+
values = JSON.parse(ZuoraConnect::AppInstance.decrypt_response(Base64.urlsafe_decode64(request["data"])))
|
|
614
|
+
values.fetch("param_data", {}).each do |k ,v|
|
|
615
|
+
params[k] = v
|
|
616
|
+
end
|
|
617
|
+
session["#{values["appInstance"]}::destroy"] = values["destroy"]
|
|
618
|
+
session["appInstance"] = values["appInstance"]
|
|
619
|
+
if values["current_user"]
|
|
620
|
+
session["#{values["appInstance"]}::admin"] = values["current_user"]["admin"] ? values["current_user"]["admin"] : false
|
|
621
|
+
session["#{values["appInstance"]}::user::timezone"] = values["current_user"]["timezone"]
|
|
622
|
+
session["#{values["appInstance"]}::user::locale"] = values["current_user"]["locale"]
|
|
623
|
+
session["#{values["appInstance"]}::user::email"] = values["current_user"]["email"]
|
|
234
624
|
end
|
|
235
625
|
|
|
236
|
-
@appinstance = ZuoraConnect::AppInstance.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
626
|
+
@appinstance = ZuoraConnect::AppInstance.find_by(:id => values["appInstance"].to_i)
|
|
627
|
+
|
|
628
|
+
if @appinstance.blank?
|
|
629
|
+
if ZuoraConnect.configuration.disable_provisioning
|
|
630
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("Provisioning is suspended")
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
Apartment::Tenant.switch!("public")
|
|
634
|
+
begin
|
|
635
|
+
Apartment::Tenant.create(values["appInstance"].to_s)
|
|
636
|
+
rescue Apartment::TenantExists => ex
|
|
637
|
+
ZuoraConnect.logger.debug("Tenant Already Exists")
|
|
638
|
+
end
|
|
639
|
+
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"]}
|
|
640
|
+
@appinstance = ZuoraConnect::AppInstance.new(mapped_values.merge({:id => values["appInstance"].to_i}))
|
|
641
|
+
@appinstance.save(:validate => false)
|
|
642
|
+
else
|
|
643
|
+
mapped_values = {:access_token => values["access_token"], :refresh_token => values["refresh_token"], :oauth_expires_at => values["expires"]}
|
|
644
|
+
@appinstance.assign_attributes(mapped_values)
|
|
645
|
+
if @appinstance.access_token_changed? && @appinstance.refresh_token_changed?
|
|
646
|
+
@appinstance.save(:validate => false)
|
|
647
|
+
else
|
|
648
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("Authorization mismatch. Possible tampering with session.")
|
|
649
|
+
end
|
|
650
|
+
end
|
|
651
|
+
else
|
|
652
|
+
if session["appInstance"].present?
|
|
653
|
+
@appinstance = ZuoraConnect::AppInstance.find_by(:id => session["appInstance"])
|
|
654
|
+
else
|
|
655
|
+
if ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(request.headers.fetch("HOST", nil))
|
|
656
|
+
render "zuora_connect/application/ldap_login", :layout => false
|
|
657
|
+
return
|
|
658
|
+
else
|
|
659
|
+
raise ZuoraConnect::Exceptions::AccessDenied.new("No application state or session found.")
|
|
660
|
+
end
|
|
661
|
+
end
|
|
241
662
|
end
|
|
242
|
-
session["#{@appinstance.id}::admin"] = ZuoraConnect.configuration.dev_mode_admin
|
|
243
663
|
end
|
|
244
664
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
665
|
+
def next_instance_id
|
|
666
|
+
min_instance_id = 24_999_999
|
|
667
|
+
(ZuoraConnect::AppInstance.all.where("id > #{min_instance_id}").order(id: :desc).limit(1).pluck(:id).first || min_instance_id) + 1
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
def new_instance(id, zuora_entity_id, rest_domain, tenant_id: nil, task_data: nil, retry_count: 0)
|
|
671
|
+
app_instance = ZuoraConnect::AppInstance.new(
|
|
672
|
+
:id => id,
|
|
673
|
+
:api_token => generate_token,
|
|
674
|
+
:token => generate_token,
|
|
675
|
+
:oauth_expires_at => Time.now + 1000.years,
|
|
676
|
+
:zuora_domain => rest_domain,
|
|
677
|
+
:zuora_entity_ids => [zuora_entity_id]
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
app_instance[:zuora_tenant_ids] = [tenant_id.to_s] if tenant_id.present?
|
|
681
|
+
|
|
682
|
+
if task_data.nil?
|
|
683
|
+
# no encryption
|
|
684
|
+
app_instance['zuora_logins'] = task_data
|
|
255
685
|
else
|
|
256
|
-
|
|
686
|
+
# kms encrypt
|
|
687
|
+
app_instance.zuora_logins = task_data
|
|
257
688
|
end
|
|
689
|
+
|
|
690
|
+
begin
|
|
691
|
+
app_instance.save(:validate => false)
|
|
692
|
+
rescue ActiveRecord::RecordNotUnique
|
|
693
|
+
raise if retry_count > 1
|
|
694
|
+
|
|
695
|
+
Thread.current[:appinstance] = nil
|
|
696
|
+
session['appInstance'] = nil
|
|
697
|
+
render 'zuora_connect/static/error_handled', :locals => {
|
|
698
|
+
:title => 'Application could not create unique tokens.',
|
|
699
|
+
:message => 'Please contact support or retry launching application.'
|
|
700
|
+
}, :layout => false
|
|
701
|
+
return
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
app_instance
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
def generate_token
|
|
708
|
+
rand(36**64).to_s(36)
|
|
258
709
|
end
|
|
259
710
|
end
|
|
260
711
|
end
|