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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +219 -0
  4. data/Rakefile +1 -1
  5. data/app/assets/javascripts/hallway_wrapper/after.js +22 -3
  6. data/app/controllers/concerns/zuora_connect/authenticate.rb +39 -0
  7. data/app/controllers/zuora_connect/api/v1/app_instance_controller.rb +5 -0
  8. data/app/controllers/zuora_connect/application_controller.rb +37 -2
  9. data/app/controllers/zuora_connect/static_controller.rb +142 -27
  10. data/app/helpers/zuora_connect/LDAP/adapter.rb +16 -0
  11. data/app/helpers/zuora_connect/LDAP/connection.rb +123 -0
  12. data/app/helpers/zuora_connect/application_helper.rb +10 -0
  13. data/app/models/concerns/zuora_connect/auditable.rb +29 -0
  14. data/app/models/zuora_connect/app_instance_base.rb +652 -180
  15. data/app/models/zuora_connect/login.rb +24 -11
  16. data/app/models/zuora_connect/telegraf.rb +18 -38
  17. data/app/models/zuora_connect/zuora_user.rb +35 -0
  18. data/app/views/sql/refresh_aggregate_table.txt +12 -10
  19. data/app/views/zuora_connect/application/ldap_login.html.erb +195 -0
  20. data/app/views/zuora_connect/static/error_handled.html.erb +76 -0
  21. data/app/views/zuora_connect/static/error_handled.js.erb +1 -0
  22. data/app/views/zuora_connect/static/error_unhandled.erb +85 -0
  23. data/app/views/zuora_connect/static/error_unhandled.js.erb +1 -0
  24. data/app/views/zuora_connect/static/launch.html.erb +71 -76
  25. data/config/initializers/object_method_hooks.rb +2 -2
  26. data/config/initializers/patches.rb +9 -0
  27. data/config/initializers/postgresql_adapter.rb +119 -1
  28. data/config/initializers/prometheus.rb +57 -23
  29. data/config/initializers/redis.rb +52 -5
  30. data/config/initializers/resque.rb +5 -1
  31. data/config/initializers/unicorn.rb +30 -2
  32. data/config/initializers/zuora_observability.rb +24 -0
  33. data/config/routes.rb +8 -3
  34. data/db/migrate/20100718151733_create_connect_app_instances.rb +1 -1
  35. data/db/migrate/20101024162319_add_tokens_to_app_instance.rb +1 -1
  36. data/db/migrate/20101024220705_add_token_to_app_instance.rb +1 -1
  37. data/db/migrate/20110131211919_add_sessions_table.rb +1 -1
  38. data/db/migrate/20110411200303_add_expiration_to_app_instance.rb +1 -1
  39. data/db/migrate/20110413191512_add_new_api_token.rb +1 -1
  40. data/db/migrate/20110503003602_add_catalog_data_to_app_instance.rb +1 -1
  41. data/db/migrate/20110503003603_add_catalog_mappings_to_app_instance.rb +1 -1
  42. data/db/migrate/20110503003604_catalog_default.rb +1 -1
  43. data/db/migrate/20180301052853_add_catalog_attempted_at.rb +1 -1
  44. data/db/migrate/20181206162339_add_fields_to_instance.rb +1 -1
  45. data/db/migrate/20190520232221_add_zuora_user_table_and_alter_app_instance_id_table.rb +18 -0
  46. data/db/migrate/20190520232222_add_unique_index.rb +6 -0
  47. data/db/migrate/20190520232223_add_provisioning_fields.rb +6 -0
  48. data/db/migrate/20190520232224_add_environment_fields.rb +16 -0
  49. data/lib/metrics/net.rb +3 -3
  50. data/lib/middleware/json_parse_errors.rb +33 -0
  51. data/lib/middleware/metrics_middleware.rb +62 -68
  52. data/lib/middleware/request_id_middleware.rb +17 -0
  53. data/lib/resque/dynamic_queues.rb +35 -13
  54. data/lib/resque/plugins/app_instance_job.rb +63 -0
  55. data/lib/resque/plugins/custom_logger.rb +12 -27
  56. data/lib/tasks/zuora_connect_tasks.rake +0 -5
  57. data/lib/zuora_connect/configuration.rb +8 -4
  58. data/lib/zuora_connect/controllers/helpers.rb +640 -189
  59. data/lib/zuora_connect/engine.rb +12 -9
  60. data/lib/zuora_connect/exceptions.rb +18 -2
  61. data/lib/zuora_connect/middleware/hallway.rb +34 -0
  62. data/lib/zuora_connect/railtie.rb +16 -39
  63. data/lib/zuora_connect/version.rb +3 -1
  64. data/lib/zuora_connect.rb +69 -5
  65. metadata +146 -126
  66. data/app/views/zuora_connect/static/invalid_app_instance_error.html.erb +0 -65
  67. data/app/views/zuora_connect/static/invalid_launch_request.html +0 -65
  68. data/app/views/zuora_connect/static/session_error.html.erb +0 -63
  69. data/config/initializers/elastic_apm.rb +0 -25
  70. data/lib/zuora_connect/views/helpers.rb +0 -9
  71. data/test/controllers/zuora_connect/api/v1/app_instance_controller_test.rb +0 -13
  72. data/test/dummy/README.rdoc +0 -28
  73. data/test/dummy/Rakefile +0 -6
  74. data/test/dummy/app/assets/javascripts/application.js +0 -13
  75. data/test/dummy/app/assets/stylesheets/application.css +0 -15
  76. data/test/dummy/app/controllers/application_controller.rb +0 -5
  77. data/test/dummy/app/helpers/application_helper.rb +0 -2
  78. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  79. data/test/dummy/bin/bundle +0 -3
  80. data/test/dummy/bin/rails +0 -4
  81. data/test/dummy/bin/rake +0 -4
  82. data/test/dummy/bin/setup +0 -29
  83. data/test/dummy/config/application.rb +0 -26
  84. data/test/dummy/config/boot.rb +0 -5
  85. data/test/dummy/config/database.yml +0 -25
  86. data/test/dummy/config/environment.rb +0 -5
  87. data/test/dummy/config/environments/development.rb +0 -41
  88. data/test/dummy/config/environments/production.rb +0 -79
  89. data/test/dummy/config/environments/test.rb +0 -42
  90. data/test/dummy/config/initializers/assets.rb +0 -11
  91. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  92. data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
  93. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  94. data/test/dummy/config/initializers/inflections.rb +0 -16
  95. data/test/dummy/config/initializers/mime_types.rb +0 -4
  96. data/test/dummy/config/initializers/session_store.rb +0 -3
  97. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  98. data/test/dummy/config/locales/en.yml +0 -23
  99. data/test/dummy/config/routes.rb +0 -4
  100. data/test/dummy/config/secrets.yml +0 -22
  101. data/test/dummy/config.ru +0 -4
  102. data/test/dummy/public/404.html +0 -67
  103. data/test/dummy/public/422.html +0 -67
  104. data/test/dummy/public/500.html +0 -66
  105. data/test/dummy/public/favicon.ico +0 -0
  106. data/test/fixtures/zuora_connect/app_instances.yml +0 -11
  107. data/test/integration/navigation_test.rb +0 -8
  108. data/test/lib/generators/zuora_connect/datatable_generator_test.rb +0 -16
  109. data/test/models/zuora_connect/app_instance_test.rb +0 -9
  110. data/test/test_helper.rb +0 -21
  111. data/test/zuora_connect_test.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b69457446868cd3b97d81d5753a967f002d58dfc750c2a4cae9b880a590c741
4
- data.tar.gz: e27a81b4e9f30562ff67632d57c3b9e798e76677b5b4ee7c2698473a349bb111
3
+ metadata.gz: 7efc37130319f941b541835b6b7186c2638d24b0e5cf64c239d53a5aecf1eb3e
4
+ data.tar.gz: ffbe881cbf369a0091b5f2d001344ed9a943cf8828f64b0f97e7fa79161ac60b
5
5
  SHA512:
6
- metadata.gz: cb57173d9c5ef615f65d42a1fb6034f47c9878840063d3d243b774ed036e3b30f82a86943b1cfccf9a6534d69849a47468a51b1978e6720a012320025120e9ae
7
- data.tar.gz: 53cad727a3c349daf72ee6f3b77c6dfebfe658f41470feb2bc259c4cd5dda994f28f00291d8fa6b14e2feda38df2acc033fef79d8875c5a8c0e6acbef083581b
6
+ metadata.gz: 24eda6ee0b68e6fbaa7a34825fa82fad61bba1cd514396ba54690478335f9d11169c863f77b5e9bad3b5a28544a93a69e5dbb4c1e51b553917c7bd3b5fc3e967
7
+ data.tar.gz: 75c2f63d6fc26ead3c21ed85547843ef601726c8f81af49b871d822a290ac6d3cb387853e70f06453ee9b042de6c9c2c17611135da2bfc65a7b8b22b6a5f78c8
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2016 Matthew Ingle
1
+ Copyright 2021 Zuora, Inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md ADDED
@@ -0,0 +1,219 @@
1
+ # Connect Gem
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/zuora_connect.svg)](https://badge.fury.io/rb/zuora_connect)
4
+
5
+ ## Requirements
6
+ This gem requires a postgres database
7
+
8
+ ## Install
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'zuora_connect'
14
+ ```
15
+
16
+ Then execute `bundle install` in your terminal
17
+
18
+ ## How to contribute to this repository
19
+ https://confluence.zuora.com/pages/viewpage.action?spaceKey=ZCP&title=Pushing+to+GIT
20
+
21
+ ## Configuration
22
+
23
+ ### Settings
24
+ This gem can be configured by adding `connect.rb` to the `config/initializers` folder. An example file and the available options can be seen below.
25
+ ```ruby
26
+ ZuoraConnect.configure do |config|
27
+ config.url = ""
28
+ config.delayed_job = false
29
+ config.default_time_zone = Time.zone
30
+ config.default_locale = :en
31
+ config.timeout = 5.minutes
32
+ config.private_key = ""
33
+ config.mode = "Production"
34
+ config.dev_mode_logins = { "target_login" => {"tenant_type" => "Zuora", "username" => "user", "password" => "pass", "url" => "url"} }
35
+ config.dev_mode_options = {"name" => {"config_name" => "name", "datatype" => "type", "value" => "value"}}
36
+ config.dev_mode_mode = "Universal"
37
+ end
38
+ ```
39
+
40
+ | Option | Description | Required | Values | Default | Example |
41
+ | -------------------- | ----------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------- | --------------------------- | ------------------------------------------ |
42
+ | url | URL for the gem to connect to | Optional | https://connect.zuora.com <br/> https://connect-staging.zuora.com <br/> localhost:3000 | "https://connect.zuora.com" | config.url = `"https://connect.zuora.com"` |
43
+ | delayed_job | Used to indicate if Delayed Job is used by this Application | Optional | true or false | `true`| `config.delayed_job - true`|
44
+ | default_time_zone | Used to indicate the default timezone for the application | Optional | A valid time zone object | `Time.zone`| `config.default_time_zone = Time.zone` |
45
+ | default_locale | Used to indicate the default locale for the application | Optional | A valid locale| `:en`| `config.default_locale = :en`|
46
+ | private_key| Used to indicate the private key to use when decrypting the data payload|Required for Production| A valid private key| `nil`|`config.private_key = File.open(#{Rails.root/private_key})`|
47
+ | timeout|Used to indicate the amount of time the current session stays active before syncing with ZuoraConnect| Optional |ActiveSupport::Duration |`5.minutes`|`config.timeout = 1.hour`|
48
+ | mode|Used to indicate current environment the gem should run against|Optional |Production or Development|`"Production"`|`config.mode = "Development"`|
49
+ | dev_mode_appinstance|Used to indicate the schema name to use when in development mode|Optional|String|`"1"` |`config.dev_mode_appinstance = "1"`|
50
+ | dev_mode_admin|Used to indicate if admin mode should be turned on in development mode. This will cause all admin calls to be evaluated to true when displaying admin only elements in your application.|Optional|true or false|`false`|`config.dev_mode_admin = true`|
51
+ | dev_mode_pass|Used to mock up the users ZuoraConnect password|Optional |String|`"Test"`|`config.dev_mode_pass = "password1"`|
52
+ | dev_mode_user|Used to mock up the users ZuoraConnect username|Optional|String|`"Test"`|`config.dev_mode_user = "User1"`|
53
+ | dev_mode_logins|Used to mock up the login payload from ZuoraConnect|Optional|Hash|`nil`| `config.dev_mode_logins= { "target_login" => {"tenant_type" => "Zuora","username" => "user","password" => "pass","url" => "url"}}`
54
+ | dev_mode_mode|Used to mock up the mode passed from ZuoraConnect|Optional |String|`"Universal" `|`config.dev_mode_mode = "Mode2"`|
55
+ | dev_mode_options|Used to mock up the options payload from ZuoraConnect|Optional |Hash|`nil`|'config.dev_mode_options ={"name" => {"config_name" => "name","datatype" => "type","value" => "value"}}'|
56
+
57
+
58
+ ### Controller Setup
59
+ The following controllers should have the below lines added to them
60
+
61
+ #### Application Controller ( `controllers/application_controller.rb`)
62
+ ```ruby
63
+ before_action :authenticate_connect_app_request
64
+ after_action :persist_connect_app_session
65
+ ```
66
+
67
+ #### Admin controllers
68
+ ```ruby
69
+ before_action :check_connect_admin!
70
+ ```
71
+
72
+ #### Admin actions inside a controllers
73
+
74
+ ```ruby
75
+ before_action :check_connect_admin!, :only => [:logs]
76
+ ```
77
+ #### API Controller
78
+ ```ruby
79
+ before_action :authenticate_app_api_request
80
+ ```
81
+
82
+ An explanation of the available before_filters and what they do can be found below
83
+
84
+ | Name | Description |
85
+ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
86
+ | authenticate_app_api_request | Authenticates the incoming request, handles data segmentation, and creates the @appinstance global variable |
87
+ | persist_connect_app_session | Saves the current user session for use after every request so that every request does not require authentication with Connect. Instead authentication to Connect is done based on the timeout value of the session set in the configuration steps above |
88
+ | check_connect_admin | Checks if the user is labeled as an admin as deemed by the encrypted request payload coming from Connect. This filter is used to lock down certain functionality that only the Developer should have access to. <br/> Returns false if the user is not an admin |
89
+ | check_connect_admin! | The filter works the same as the above but instead raises an exception `ZuoraConnect::Exceptions::AccessDenied` |
90
+ | authenticate_app_api_request | Authenticates the incoming API request based on the token passed in. The token must match a token associate to one of the available app instances. This token is stored on the app instance object as api_token. More information can be found in the API authentication section below. |
91
+
92
+ ## Usage
93
+
94
+ The Connect gem provides an integration with ZuoraConnect by allowing the application to read data from Connect and make the appropriate API calls.
95
+
96
+ ### Data Segmentation
97
+
98
+ The Connect Gem provides an integration with ZuoraConnect by allowing the application to read data from Connect and make the appropriate API calls.
99
+
100
+ ### The App Instance object
101
+
102
+ #### Methods and Attributes
103
+
104
+ | Name | Type | Description | Example |
105
+ | ------------ | ----------- | ------------ | --------------------------- |
106
+ | new_session | `Method` | | @appinstance.new_sesion |
107
+ | updateOption | `Method` | | @appinstance.updateOption() |
108
+ | options | `Attribute` | | @appinstance.options |
109
+ | mode | `Attribute` | | @appinstance.mode |
110
+ | logins | `Attribute` | | @appinstance.logins |
111
+ | task_data | `Attribute` | | @appinstance.task_data |
112
+ | token | `Attribute` | `DEPRECATED` | @appinstance.token |
113
+ | api_token | `Attribute` | | @appinstance.api_token |
114
+
115
+ #### Accessing the Object
116
+
117
+ The `@appinstance` object is accessible in every View and Controller in your application. In order to access `@appinstance` in a Model it must be pulled out of the current thread by doing the following:
118
+ ```ruby
119
+ @appinstance = Thread.current[:appinstance]
120
+ ```
121
+ ### Login Object
122
+
123
+ All Login information available to your app is passed from connect in a hash in the form `{:target_login => data, :source_login => data}`. It is important to note that target_login and source_login can be variable and that any number of logins can be passed to your application as defined by Connect. For example the following use case could exist: `{:zuora_login => data, :system1_login => data,:system2_login => data}`. This information can be retrieved by the @appinstance object through a call similiar to this `@appinstance.system2_login`. This removes the requirement of using `@appinstance.logins `and looping through the returned hash if you are aware of the logins that Connect will be sending your application.
124
+
125
+ Each login is mapped as a login object associated to the `@appinstance` object. Every attribute associated to this object passed from Connect is available on this object as an attribute. At a minimum the below attributes will be available
126
+
127
+
128
+ | Name | Description |
129
+ | ----------- | ------------------------------------------ |
130
+ | tenant_type | Login type such as "Zuora" or "Salesforce" |
131
+ | username | The username |
132
+ | password | The password |
133
+ | url | Endpoint or URL |
134
+
135
+ #### Zuora logins
136
+ The Connect Gem has built-in integration with the Zuora gem and automatically creates a ZuoraLogin object for every Zuora login. This can be accessed by executing something similiar to the following:
137
+ ```ruby
138
+ @appinstance.target_login.client.rest_call
139
+ ```
140
+
141
+ ### Admin authentication
142
+
143
+ #### Controller
144
+
145
+ Authentication is done through a before filter. Reference the above section on controller setup
146
+
147
+ #### View
148
+
149
+ `is_app_admin?` is a view helper that returns true if the user is an admin
150
+
151
+ ### API Authentication
152
+
153
+ In order to allow direct access to the application without Connect for API calls the :authenticate_app_api_request before filter must be used in your controller and both authenticate_connect_app_request and persist_connect_app_session filters should be skipped to avoid collision.
154
+
155
+ When making an API call to your application the token associated to the `@appinstance` object must be passed in as the password in a basic auth header with the username being the users Connect username or in the access_token param
156
+
157
+ ## Rails Console
158
+
159
+ By Default all queries executed from Rails Console will filter against schemas that are named “Public” and your current system $user. You can verify this by executing `ActiveRecord::Base.connection.schema_search_path` in rails console which should return “”$user", public"
160
+
161
+ The Connect Gem will create/use schemas tied to the TaskIds coming out of Connect. In Development mode this TaskId will default to 1. To query data out in development mode you would open up rails console and execute `ActiveRecord::Base.connection.schema_search_path = 1` before proceeding to subsequent queries
162
+
163
+ ## Delayed Job
164
+
165
+ In order to use delayed job the configuration option “delayed_job” must be set to true for jobs to be picked up by your workers
166
+
167
+ ### Installation
168
+ 1. Set `config.delayed_job = true` in `config/initializers/connect.rb`
169
+ 2. Add the following line to the connect.rb init file `Dir["#{Rails.root}/lib/workers/*.rb"].each {|file| require file }`
170
+ 3. Add the following gems to your gem file
171
+ ```ruby
172
+ gem "delayed_job"
173
+ gem "delayed_job_active_record"
174
+ gem "daemons"
175
+ gem "delayed_job_web" #Optional if a web interface is needed for job management
176
+ ```
177
+ 4. Run `rails generate delayed_job:active_record` in the terminal
178
+ 5. Add `config.active_job.queue_adapter = :delayed_job` to `config/application.rb`
179
+
180
+ ### Usage
181
+
182
+ #### Creating a Worker Class
183
+
184
+ Add a worker file based on the following template to lib/workers/worker.rb
185
+ ```ruby
186
+ class Worker
187
+ attr_accessor :schema
188
+ def initialize(instance_id,var2)
189
+ @instance_id = instance_id
190
+ @var2 = var2
191
+ @schema = ActiveRecord::Base.connection.schema_search_path
192
+ end
193
+
194
+ def perform()
195
+ @appinstance = ZuoraConnect::AppInstance.find(@instance_id)
196
+ @appinstance.new_session()
197
+ end
198
+ end
199
+ ```
200
+
201
+ #### Queueing Jobs
202
+
203
+ Jobs can be queued anywhere in the code base by using the following code `Delayed::Job.enqueue(Worker.new(@appinstance.id, var2))`. Note that instead of passing in the @appinstance object we always pass in the id. This must happen for schema segmentation to work correctly. This can be disregarded if your worker is not processing data specific to a users app instance.
204
+
205
+ Reference [here](https://github.com/collectiveidea/delayed_job) for more information on Running Jobs and creating workers
206
+
207
+ #### Starting the delayed job daemon
208
+
209
+ Run `bin/delayed_job -n 2 restart` in your terminal to start 2 processes that will pick up all queued jobs
210
+
211
+ ### License Information
212
+ IN THE EVENT YOU ARE AN EXISTING ZUORA CUSTOMER, USE OF THIS SOFTWARE IS GOVERNED BY THE MIT LICENSE SET FORTH BELOW AND NOT THE MASTER SUBSCRIPTION AGREEMENT OR OTHER COMMERCIAL AGREEMENT ENTERED INTO BETWEEN YOU AND ZUORA (“AGREEMENT”). FOR THE AVOIDANCE OF DOUBT, ZUORA’S OBLIGATIONS WITH RESPECT TO TECHNICAL SUPPORT, UPTIME, INDEMNIFICATION, AND SECURITY SET FORTH IN THE AGREEMENT DO NOT APPLY TO THE USE OF THIS SOFTWARE.
213
+
214
+ Copyright 2021 Zuora, Inc.
215
+
216
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
217
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
218
+
219
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
15
15
  rdoc.rdoc_files.include('lib/**/*.rb')
16
16
  end
17
17
 
18
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
19
19
  load 'rails/tasks/engine.rake'
20
20
 
21
21
 
@@ -4,12 +4,31 @@ window.define = previousDefine;
4
4
  if (isHallway()) {
5
5
  $( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
6
6
  if ( jqxhr.status === 401) {
7
- window.location.href = '/apps/newlogin.do?retURL=' + window.location.pathname;
7
+ fetch("https://" + window.location.host + "/apps/v1/navigation").then(response => {
8
+ if (response.status === 401) {
9
+ deleteAllCookies();
10
+ window.location.href = '/apps/newlogin.do?retURL=' + window.location.pathname;
11
+ }
12
+ });
8
13
  }
9
14
  });
10
15
  }
11
16
 
12
17
  function isHallway() {
13
- var regex = new RegExp("^/services/");
14
- return window.location.pathname.match(regex);
18
+ var regex = new RegExp("(?<=\\/)services\\/.*");
19
+ if (regex.test(window.location.pathname)) {
20
+ return window.location.pathname.match(regex)[0]
21
+ }
22
+ return null;
23
+ }
24
+
25
+ function deleteAllCookies() {
26
+ var cookies = document.cookie.split(";");
27
+
28
+ for (var i = 0; i < cookies.length; i++) {
29
+ var cookie = cookies[i];
30
+ var eqPos = cookie.indexOf("=");
31
+ var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
32
+ document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/";
33
+ }
15
34
  }
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ZuoraConnect
4
+ # Methods for authenticating and setting the app instance for the current user
5
+ module Authenticate
6
+ extend ActiveSupport::Concern
7
+
8
+ def setup_instance_via_dev_mode
9
+ app_instance_id = ZuoraConnect.configuration.dev_mode_appinstance
10
+ session['appInstance'] = app_instance_id
11
+ session["#{app_instance_id}::admin"] = ZuoraConnect.configuration.dev_mode_admin
12
+
13
+ values = {
14
+ id: app_instance_id,
15
+ access_token: ZuoraConnect.configuration.dev_mode_user,
16
+ refresh_token: ZuoraConnect.configuration.dev_mode_pass,
17
+ token: ZuoraConnect.configuration.dev_mode_pass + ZuoraConnect.configuration.dev_mode_pass,
18
+ api_token: ZuoraConnect.configuration.dev_mode_pass + ZuoraConnect.configuration.dev_mode_pass
19
+ }
20
+
21
+ @appinstance = ZuoraConnect::AppInstance.find_by(id: app_instance_id)
22
+ ZuoraConnect::ZuoraUser.current_user_id = 0
23
+ zuora_org_ids = cookies['Zuora-Org-Ids'] || request.headers['Zuora-Org-Ids']
24
+ ZuoraConnect::ZuoraUser.current_org_ids = zuora_org_ids.split('|') if zuora_org_ids
25
+ if @appinstance.blank?
26
+ Apartment::Tenant.switch!('public')
27
+ begin
28
+ Apartment::Tenant.create(app_instance_id)
29
+ rescue Apartment::TenantExists
30
+ Apartment::Tenant.drop(app_instance_id)
31
+ retry
32
+ end
33
+ @appinstance = ZuoraConnect::AppInstance.new
34
+ end
35
+ @appinstance.assign_attributes(values)
36
+ @appinstance.save(validate: false)
37
+ end
38
+ end
39
+ end
@@ -43,7 +43,12 @@ module ZuoraConnect
43
43
 
44
44
  def cache_bust
45
45
  if defined?(Redis.current)
46
+ @appinstance.fetch_connect_data #Fetch data and set in database if kms key is used
47
+ @appinstance.cache_app_instance(force_cache: true) #Update cache in redis
46
48
  Redis.current.del("AppInstance:#{@appinstance.id}")
49
+ @appinstance.cache_app_instance(force_cache: true) #Update cache in redis
50
+ #TODO: Could be a chance another thread cache back to old value, but will eventually cache will get consitent, move to nolonger needing redis cache
51
+
47
52
  respond_to do |format|
48
53
  format.json {render json: {}, status: :ok}
49
54
  end
@@ -1,8 +1,43 @@
1
1
  module ZuoraConnect
2
2
  class ApplicationController < ActionController::Base
3
3
  protect_from_forgery with: :exception
4
- before_action :authenticate_connect_app_request
5
- after_action :persist_connect_app_session
4
+ before_action :authenticate_connect_app_request, except: [:ldap_login]
5
+ after_action :persist_connect_app_session, except: [:ldap_login]
6
+ skip_before_action :verify_authenticity_token, :only => [:ldap_login]
7
+
8
+ def ldap_login
9
+ if !ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(request.headers.fetch("HOST", nil))
10
+ render 'zuora_connect/application/ldap_login', locals: {
11
+ title: 'Internal Auth Failure',
12
+ message: 'Internal Auth Failure'
13
+ }, :layout => false
14
+ end
6
15
 
16
+ require 'net-ldap'
17
+
18
+ username = request.parameters['ldap_username']
19
+ password = request.parameters['ldap_password']
20
+
21
+ begin
22
+ if ZuoraConnect::LDAP::Adapter.valid_credentials?(username, password)
23
+ id = ZuoraConnect::AppInstance.first.id
24
+ session["appInstance"] = ZuoraConnect::AppInstance.first.id
25
+ session["#{id}::admin"] = true
26
+ respond_to do |format|
27
+ format.html { redirect_to '/admin/app_instances' }
28
+ end
29
+ else
30
+ render 'zuora_connect/application/ldap_login', locals: {
31
+ title: 'LDAP Authentication Failed',
32
+ message: 'Invalid username or password'
33
+ }, :layout => false
34
+ end
35
+ rescue Net::LDAP::Error
36
+ render 'zuora_connect/application/ldap_login', locals: {
37
+ title: 'LDAP Authentication Net Error',
38
+ message: 'Failed to connect to server while authenticating the LDAP credentials. Please retry later.'
39
+ }, :layout => false
40
+ end
41
+ end
7
42
  end
8
43
  end
@@ -1,31 +1,27 @@
1
1
  module ZuoraConnect
2
+ require "resolv"
2
3
  class StaticController < ApplicationController
3
- before_action :authenticate_connect_app_request, :except => [:metrics, :health, :session_error, :invalid_app_instance_error, :initialize_app]
4
- before_action :clear_connect_app_session, :only => [:metrics, :health, :session_error, :invalid_app_instance_error, :initialize_app]
5
- after_action :persist_connect_app_session, :except => [:metrics, :health, :session_error, :invalid_app_instance_error, :initialize_app]
6
-
7
- skip_before_action :verify_authenticity_token, :only => [:initialize_app]
4
+ before_action :authenticate_connect_app_request, :except => [:health, :initialize_app, :provision, :instance_user, :instance_drop]
5
+ before_action :clear_connect_app_session, :only => [:health, :initialize_app, :provision, :instance_user, :instance_drop]
6
+ after_action :persist_connect_app_session, :except => [:health, :initialize_app, :provision, :instance_user, :instance_drop]
8
7
 
9
- def session_error
10
- respond_to do |format|
11
- format.html
12
- format.json { render json: { message: "Session Error", status: 500 }, status: 500 }
13
- end
14
- end
8
+ skip_before_action :verify_authenticity_token, :only => [:initialize_app, :provision, :instance_drop]
9
+ http_basic_authenticate_with name: ENV['PROVISION_USER'], password: ENV['PROVISION_SECRET'], :only => [:provision, :instance_user, :instance_drop]
15
10
 
16
- def invalid_app_instance_error
17
- respond_to do |format|
18
- format.html
19
- format.json {render json: { message: "Invalid App Instance", status: 500 }, status: 500 }
11
+ def health
12
+ if params[:error].present?
13
+ begin
14
+ raise ZuoraConnect::Exceptions::Error.new('This is an error')
15
+ rescue => ex
16
+ case params[:error]
17
+ when 'Log'
18
+ Rails.logger.error("Error in Health", ex)
19
+ when 'Exception'
20
+ raise
21
+ end
22
+ end
20
23
  end
21
- end
22
24
 
23
- def metrics
24
- type = params[:type].present? ? params[:type] : "versions"
25
- render json: ZuoraConnect::AppInstance.get_metrics(type).to_json, status: 200
26
- end
27
-
28
- def health
29
25
  render json: {
30
26
  message: "Alive",
31
27
  status: 200
@@ -35,14 +31,133 @@ module ZuoraConnect
35
31
  def initialize_app
36
32
  begin
37
33
  authenticate_connect_app_request
34
+ unless performed?
35
+ @appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
36
+ render json: {
37
+ message: 'Success',
38
+ status: 200
39
+ }, status: 200
40
+ end
41
+ rescue => ex
42
+ Rails.logger.error("Failed to Initialize application", ex)
43
+ if performed?
44
+ Rails.logger.error("Failed to Initialize application #{performed?}", ex)
45
+ else
46
+ render json: {
47
+ message: "Failure initializing app instance",
48
+ status: 500
49
+ }, status: 500
50
+ end
51
+ end
52
+ end
53
+
54
+ def provision
55
+ if ZuoraConnect.configuration.disable_provisioning
56
+ render(json: { status: 403, message: 'Provisioning is suspended' }, status: 403) && return
57
+ end
58
+
59
+ create_new_instance
60
+ unless performed?
38
61
  render json: {
39
- message: "Success",
40
- status: 200
62
+ status: 200,
63
+ message: 'Success',
64
+ app_instance_id: @appinstance.id
41
65
  }, status: 200
42
- rescue
66
+ end
67
+ rescue StandardError => e
68
+ message = 'Failed to provision new instance'
69
+ if performed?
70
+ Rails.logger.error("#{message}: #{performed?}", e)
71
+ else
72
+ Rails.logger.error(message, e)
73
+ render json: {
74
+ status: 500,
75
+ message: message
76
+ }, status: 500
77
+ end
78
+ end
79
+
80
+ def instance_user
81
+ ZuoraConnect::AppInstance.read_master_db do
82
+ ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
83
+ Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
84
+
85
+ if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
86
+ ElasticAPM.set_label(:trace_id, request.uuid)
87
+ end
88
+
89
+ unless params[:id].present?
90
+ render json: {
91
+ status: 400,
92
+ message: 'No app instance id provided'
93
+ }, status: :bad_request
94
+ return
95
+ end
96
+
97
+ @appinstance = ZuoraConnect::AppInstance.find(params[:id]).new_session
98
+ end
99
+
100
+ zuora_client = @appinstance.send(ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION).client
101
+ client_describe, = zuora_client.rest_call(
102
+ url: zuora_client.rest_endpoint('genesis/user/info').gsub('v1/', ''),
103
+ session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic
104
+ )
105
+
106
+ render json: {
107
+ status: 200,
108
+ message: 'Success',
109
+ user_id: client_describe['coreUserId'],
110
+ username: client_describe['username'],
111
+ email: client_describe['workEmail']
112
+ }, status: 200
113
+ rescue ActiveRecord::RecordNotFound
114
+ render json: {
115
+ status: 400,
116
+ message: 'No app instance found'
117
+ }, status: :bad_request
118
+ rescue StandardError => e
119
+ Rails.logger.error('Error occurred getting user details', e)
120
+ render json: {
121
+ status: 500,
122
+ message: 'Failed to get user details'
123
+ }, status: 500
124
+ end
125
+
126
+ def instance_drop
127
+ host = request.headers.fetch("HOST", nil)
128
+ if host.present? && (ZuoraConnect::AppInstance::INTERNAL_HOSTS.include?(host) || host =~ Resolv::IPv4::Regex)
129
+ ZuoraConnect::AppInstance.read_master_db do
130
+ instance_id = params[:id]
131
+ @appinstance = ZuoraConnect::AppInstance.find(instance_id)
132
+ if @appinstance.drop_instance
133
+ ZuoraConnect::AppInstance.destroy(instance_id)
134
+ msg = Apartment::Tenant.drop(instance_id)
135
+
136
+ if msg.error_message.present?
137
+ render json: { "message" => msg.error_message }, status: :bad_request
138
+ else
139
+ render json: {
140
+ status: 200,
141
+ message: 'Success',
142
+ app_instance_id: instance_id
143
+ }, status: 200
144
+ end
145
+ else
146
+ render json: { "message" => @appinstance.drop_message }, status: :bad_request
147
+ end
148
+ end
149
+ else
150
+ render json: { "message" => "Host #{host} is not internal" }, status: :bad_request
151
+ end
152
+ rescue StandardError => e
153
+ message = 'Failed to drop instance'
154
+ if performed?
155
+ Rails.logger.error("#{message}: #{performed?}", e)
156
+ else
157
+ Rails.logger.error(message, e)
43
158
  render json: {
44
- message: "Failure initializing app instance",
45
- status: 500
159
+ status: 500,
160
+ message: message
46
161
  }, status: 500
47
162
  end
48
163
  end
@@ -0,0 +1,16 @@
1
+ module ZuoraConnect
2
+ module LDAP
3
+ module Adapter
4
+ def self.valid_credentials?(login, password_plaintext)
5
+ options = {
6
+ login: login,
7
+ password: password_plaintext,
8
+ ldap_auth_username_builder: proc { |attribute, login, _| "#{attribute}=#{login}" },
9
+ admin: true
10
+ }
11
+ ldap_connection = ZuoraConnect::LDAP::Connection.new(options)
12
+ ldap_connection.authorized?
13
+ end
14
+ end
15
+ end
16
+ end