solid_queue_monitor 2.0.0 → 2.2.0
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/README.md +70 -0
- data/app/assets/javascripts/solid_queue_monitor/application.js +3 -1
- data/app/controllers/solid_queue_monitor/application_controller.rb +13 -2
- data/app/controllers/solid_queue_monitor/assets_controller.rb +4 -0
- data/app/helpers/solid_queue_monitor/application_helper.rb +17 -0
- data/app/views/layouts/solid_queue_monitor/application.html.erb +1 -0
- data/app/views/solid_queue_monitor/failed_jobs/_row.html.erb +2 -0
- data/app/views/solid_queue_monitor/failed_jobs/index.html.erb +1 -0
- data/app/views/solid_queue_monitor/jobs/_header.html.erb +3 -0
- data/app/views/solid_queue_monitor/overview/_recent_job_row.html.erb +2 -0
- data/app/views/solid_queue_monitor/queues/_job_row.html.erb +2 -0
- data/app/views/solid_queue_monitor/queues/_row.html.erb +2 -0
- data/app/views/solid_queue_monitor/queues/show.html.erb +2 -0
- data/app/views/solid_queue_monitor/scheduled_jobs/index.html.erb +1 -0
- data/app/views/solid_queue_monitor/workers/_row.html.erb +1 -0
- data/app/views/solid_queue_monitor/workers/index.html.erb +1 -1
- data/lib/generators/solid_queue_monitor/templates/initializer.rb +7 -0
- data/lib/solid_queue_monitor/version.rb +1 -1
- data/lib/solid_queue_monitor.rb +13 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4f1ef08bb05ef11d7b29d511beea231cab0d1a8e1b16fc88d6c0d1fd540660b1
|
|
4
|
+
data.tar.gz: 310ff85731b0aa63432b03f909b39eb942a0eeccf59fc4956673c50561f70582
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7df976149fe809482b5a7a2299a431957174582d5134b7080942420595a469a645fae5541082a326e035b3b05fbc355f001d31eb06377b7a1275101139f735a
|
|
7
|
+
data.tar.gz: 4e32adbbba30b69d0eea3eb106d68172d8d35ae00a3ae111eb1f560337bee25708b63d5654466cd1c47e49a1d37e3e51979e2a51ac6e5412f975ad00be1a798e
|
data/README.md
CHANGED
|
@@ -123,7 +123,14 @@ SolidQueueMonitor.setup do |config|
|
|
|
123
123
|
|
|
124
124
|
# Disable the chart on the overview page to skip chart queries entirely
|
|
125
125
|
# config.show_chart = true
|
|
126
|
+
|
|
127
|
+
# Enable CSRF protection for the dashboard's destructive actions (opt-in)
|
|
128
|
+
# config.csrf_protection_enabled = false
|
|
126
129
|
end
|
|
130
|
+
|
|
131
|
+
# Optional: inherit from a host-app controller to plug into your existing auth.
|
|
132
|
+
# See "Custom Authentication" below. Defaults to "ActionController::Base".
|
|
133
|
+
# SolidQueueMonitor.base_controller_class = 'AdminController'
|
|
127
134
|
```
|
|
128
135
|
|
|
129
136
|
### Performance at Scale
|
|
@@ -136,6 +143,27 @@ If you don't need the job activity chart, disable it to skip chart queries entir
|
|
|
136
143
|
config.show_chart = false
|
|
137
144
|
```
|
|
138
145
|
|
|
146
|
+
### CSRF Protection
|
|
147
|
+
|
|
148
|
+
The dashboard's destructive actions (retry, discard, pause, resume, execute, reject, remove/prune workers) are all `POST` requests. By default CSRF protection is **disabled**, because the gem does not assume the host application has a session store (it works in API-only apps without one).
|
|
149
|
+
|
|
150
|
+
If your host app has a session store and the dashboard is mounted on the same origin, you should enable CSRF protection:
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
config.csrf_protection_enabled = true
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
When enabled:
|
|
157
|
+
|
|
158
|
+
- All dashboard forms embed an `authenticity_token`, and `csrf_meta_tags` are added to the layout for JS/`fetch`-driven requests.
|
|
159
|
+
- Unverified `POST` requests are rejected by Rails' standard `verify_authenticity_token` (returns `422 Unprocessable Entity`). Safe methods (`GET`/`HEAD`) pass through.
|
|
160
|
+
|
|
161
|
+
Requirements:
|
|
162
|
+
|
|
163
|
+
- The host app has a session store configured (e.g. `config.session_store :cookie_store`).
|
|
164
|
+
- `config.api_only` is not enabled (or session middleware is otherwise present).
|
|
165
|
+
- The dashboard is mounted on the same origin as the host app, so `form_authenticity_token` works.
|
|
166
|
+
|
|
139
167
|
### Authentication
|
|
140
168
|
|
|
141
169
|
By default, Solid Queue Monitor does not require authentication to access the dashboard. This makes it easy to get started in development environments.
|
|
@@ -159,6 +187,48 @@ config.username = -> { Rails.application.credentials.dig(:solid_queue_monitor, :
|
|
|
159
187
|
config.password = -> { Rails.application.credentials.dig(:solid_queue_monitor, :password) }
|
|
160
188
|
```
|
|
161
189
|
|
|
190
|
+
### Custom Authentication
|
|
191
|
+
|
|
192
|
+
By default, Solid Queue Monitor uses HTTP Basic auth with the username/password from `SolidQueueMonitor.setup`. To integrate with your app's existing auth (Devise, Pundit, OmniAuth, custom sessions, etc.), point the engine at a base controller from your host app:
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
# config/initializers/solid_queue_monitor.rb
|
|
196
|
+
SolidQueueMonitor.setup do |config|
|
|
197
|
+
config.authentication_enabled = false # disable HTTP Basic
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Inherit from your own controller so its before_actions, rescue_froms,
|
|
201
|
+
# layout, and current_user helper cascade into the engine.
|
|
202
|
+
SolidQueueMonitor.base_controller_class = 'AdminController'
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Minimal example — just authenticate:**
|
|
206
|
+
|
|
207
|
+
```ruby
|
|
208
|
+
class AdminController < ApplicationController
|
|
209
|
+
before_action :authenticate_user! # Devise (or your equivalent)
|
|
210
|
+
end
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Richer example — require an admin role:**
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
class AdminController < ApplicationController
|
|
217
|
+
before_action :authenticate_user!
|
|
218
|
+
before_action :require_admin
|
|
219
|
+
|
|
220
|
+
private
|
|
221
|
+
|
|
222
|
+
def require_admin
|
|
223
|
+
redirect_to root_path, alert: 'Not authorized' unless current_user&.admin?
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Leave `authentication_enabled = true` if you want HTTP Basic to run *on top of* your host auth (host runs first, HTTP Basic second). Most adopters disable it.
|
|
229
|
+
|
|
230
|
+
Restart your server after changing this config — the class hierarchy is set at load time, so config changes won't take effect on a live process.
|
|
231
|
+
|
|
162
232
|
## Usage
|
|
163
233
|
|
|
164
234
|
After installation, visit `/solid_queue` in your browser to access the dashboard.
|
|
@@ -322,7 +322,9 @@
|
|
|
322
322
|
function bulkSubmit(action, promptMsg) {
|
|
323
323
|
var ids = checkedBoxes().map(function (checkbox) { return checkbox.value; });
|
|
324
324
|
if (ids.length === 0 || !window.confirm(promptMsg)) return;
|
|
325
|
-
|
|
325
|
+
// Only clear previously-appended job id inputs. Other hidden inputs
|
|
326
|
+
// (e.g. the CSRF authenticity_token) must be preserved.
|
|
327
|
+
Array.prototype.slice.call(form.querySelectorAll('input[type="hidden"][name="job_ids[]"]')).forEach(function (input) { input.remove(); });
|
|
326
328
|
form.action = action;
|
|
327
329
|
ids.forEach(function (id) { appendHidden('job_ids[]', id); });
|
|
328
330
|
form.submit();
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
|
-
class ApplicationController < ActionController::Base
|
|
4
|
+
class ApplicationController < SolidQueueMonitor.base_controller_class.safe_constantize || ActionController::Base
|
|
5
5
|
include ActionController::HttpAuthentication::Basic::ControllerMethods
|
|
6
6
|
include ActionController::Flash
|
|
7
7
|
|
|
8
|
+
# Explicitly include the engine's helpers so they remain available when the
|
|
9
|
+
# host configures a custom base_controller_class. Rails auto-includes engine
|
|
10
|
+
# helpers only when the parent is ActionController::Base; inheriting from a
|
|
11
|
+
# host controller short-circuits that, breaking view methods like render_chart.
|
|
12
|
+
helper SolidQueueMonitor::Engine.helpers
|
|
13
|
+
|
|
8
14
|
before_action :authenticate, if: -> { SolidQueueMonitor::AuthenticationService.authentication_required? }
|
|
9
15
|
layout 'solid_queue_monitor/application'
|
|
10
|
-
|
|
16
|
+
|
|
17
|
+
# CSRF protection is opt-in (config.csrf_protection_enabled). By default the
|
|
18
|
+
# token check is skipped so the dashboard works in hosts without a session
|
|
19
|
+
# store. When the host enables it, the standard verify_authenticity_token
|
|
20
|
+
# before_action runs and unverified POSTs are rejected.
|
|
21
|
+
skip_before_action :verify_authenticity_token, unless: -> { SolidQueueMonitor.csrf_protection_enabled }
|
|
11
22
|
|
|
12
23
|
def set_flash_message(message, type)
|
|
13
24
|
# Store in instance variable for access in views
|
|
@@ -4,6 +4,10 @@ module SolidQueueMonitor
|
|
|
4
4
|
class AssetsController < ApplicationController
|
|
5
5
|
skip_before_action :authenticate, raise: false
|
|
6
6
|
|
|
7
|
+
# Public read-only assets: exempt from CSRF so the cross-origin JavaScript
|
|
8
|
+
# guard doesn't reject GETs for the JS asset when csrf_protection_enabled.
|
|
9
|
+
skip_forgery_protection
|
|
10
|
+
|
|
7
11
|
MIME_TYPES = { '.css' => 'text/css', '.js' => 'application/javascript' }.freeze
|
|
8
12
|
FINGERPRINT_PATTERN = /\A(?<base>[A-Za-z0-9_]+)-(?<hash>[a-f0-9]+)(?<ext>\.css|\.js)\z/
|
|
9
13
|
|
|
@@ -25,6 +25,23 @@ module SolidQueueMonitor
|
|
|
25
25
|
type.to_s == 'success' ? 'message-success' : 'message-error'
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# Hidden authenticity_token field for raw HTML POST forms.
|
|
29
|
+
# Renders nothing unless CSRF protection is enabled, so hosts without a
|
|
30
|
+
# session store are unaffected (form_authenticity_token needs a session).
|
|
31
|
+
def csrf_token_field_if_enabled
|
|
32
|
+
return ''.html_safe unless SolidQueueMonitor.csrf_protection_enabled
|
|
33
|
+
|
|
34
|
+
hidden_field_tag(:authenticity_token, form_authenticity_token)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# CSRF meta tags for JS/fetch-driven POSTs (defense in depth).
|
|
38
|
+
# Only emitted when CSRF protection is enabled, for the same reason.
|
|
39
|
+
def csrf_meta_tags_if_enabled
|
|
40
|
+
return ''.html_safe unless SolidQueueMonitor.csrf_protection_enabled
|
|
41
|
+
|
|
42
|
+
csrf_meta_tags
|
|
43
|
+
end
|
|
44
|
+
|
|
28
45
|
def queue_link(queue_name, css_class: nil)
|
|
29
46
|
return '-' if queue_name.blank?
|
|
30
47
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<title>Solid Queue Monitor - <%= content_for?(:title) ? yield(:title) : 'Dashboard' %></title>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<%= csrf_meta_tags_if_enabled %>
|
|
7
8
|
<%= stylesheet_link_tag asset_url_for('application.css'), nonce: content_security_policy_nonce %>
|
|
8
9
|
</head>
|
|
9
10
|
<body class="solid_queue_monitor"
|
|
@@ -13,12 +13,14 @@
|
|
|
13
13
|
<td class="actions-cell">
|
|
14
14
|
<div class="job-actions">
|
|
15
15
|
<form method="post" action="<%= retry_failed_job_path(id: job.id) %>" class="inline-form">
|
|
16
|
+
<%= csrf_token_field_if_enabled %>
|
|
16
17
|
<button type="submit" class="action-button retry-button">Retry</button>
|
|
17
18
|
</form>
|
|
18
19
|
<form method="post"
|
|
19
20
|
action="<%= discard_failed_job_path(id: job.id) %>"
|
|
20
21
|
class="inline-form"
|
|
21
22
|
data-confirm="Are you sure you want to discard this job?">
|
|
23
|
+
<%= csrf_token_field_if_enabled %>
|
|
22
24
|
<button type="submit" class="action-button discard-button">Discard</button>
|
|
23
25
|
</form>
|
|
24
26
|
</div>
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
17
|
<form method="post" id="failed-jobs-form">
|
|
18
|
+
<%= csrf_token_field_if_enabled %>
|
|
18
19
|
<% columns = [
|
|
19
20
|
{ sort_key: nil, label: tag.input(type: 'checkbox', id: 'select-all', class: 'select-all-checkbox') },
|
|
20
21
|
{ sort_key: :class_name, label: 'Job' },
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
<div class="job-actions">
|
|
16
16
|
<% if @failed_execution %>
|
|
17
17
|
<form action="<%= retry_failed_job_path(id: @failed_execution.id) %>" method="post" class="inline-form">
|
|
18
|
+
<%= csrf_token_field_if_enabled %>
|
|
18
19
|
<input type="hidden" name="redirect_to" value="<%= job_path(@job) %>">
|
|
19
20
|
<button type="submit" class="action-button retry-button">Retry</button>
|
|
20
21
|
</form>
|
|
@@ -22,12 +23,14 @@
|
|
|
22
23
|
method="post"
|
|
23
24
|
class="inline-form"
|
|
24
25
|
data-confirm="Are you sure you want to discard this job?">
|
|
26
|
+
<%= csrf_token_field_if_enabled %>
|
|
25
27
|
<input type="hidden" name="redirect_to" value="<%= failed_jobs_path %>">
|
|
26
28
|
<button type="submit" class="action-button discard-button">Discard</button>
|
|
27
29
|
</form>
|
|
28
30
|
<% end %>
|
|
29
31
|
<% if @scheduled_execution %>
|
|
30
32
|
<form action="<%= execute_scheduled_job_path(id: @scheduled_execution.id) %>" method="post" class="inline-form">
|
|
33
|
+
<%= csrf_token_field_if_enabled %>
|
|
31
34
|
<input type="hidden" name="redirect_to" value="<%= scheduled_jobs_path %>">
|
|
32
35
|
<button type="submit" class="action-button retry-button">Execute Now</button>
|
|
33
36
|
</form>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
<% if failed_execution %>
|
|
11
11
|
<div class="job-actions">
|
|
12
12
|
<form method="post" action="<%= retry_failed_job_path(id: failed_execution.id) %>" class="inline-form">
|
|
13
|
+
<%= csrf_token_field_if_enabled %>
|
|
13
14
|
<input type="hidden" name="redirect_to" value="<%= root_path %>">
|
|
14
15
|
<button type="submit" class="action-button retry-button">Retry</button>
|
|
15
16
|
</form>
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
action="<%= discard_failed_job_path(id: failed_execution.id) %>"
|
|
18
19
|
class="inline-form"
|
|
19
20
|
data-confirm="Are you sure you want to discard this job?">
|
|
21
|
+
<%= csrf_token_field_if_enabled %>
|
|
20
22
|
<input type="hidden" name="redirect_to" value="<%= root_path %>">
|
|
21
23
|
<button type="submit" class="action-button discard-button">Discard</button>
|
|
22
24
|
</form>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
<% if failed_execution %>
|
|
11
11
|
<div class="job-actions">
|
|
12
12
|
<form method="post" action="<%= retry_failed_job_path(id: failed_execution.id) %>" class="inline-form">
|
|
13
|
+
<%= csrf_token_field_if_enabled %>
|
|
13
14
|
<input type="hidden" name="redirect_to" value="<%= queue_details_path(queue_name: @queue_name) %>">
|
|
14
15
|
<button type="submit" class="action-button retry-button">Retry</button>
|
|
15
16
|
</form>
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
action="<%= discard_failed_job_path(id: failed_execution.id) %>"
|
|
18
19
|
class="inline-form"
|
|
19
20
|
data-confirm="Are you sure you want to discard this job?">
|
|
21
|
+
<%= csrf_token_field_if_enabled %>
|
|
20
22
|
<input type="hidden" name="redirect_to" value="<%= queue_details_path(queue_name: @queue_name) %>">
|
|
21
23
|
<button type="submit" class="action-button discard-button">Discard</button>
|
|
22
24
|
</form>
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
<td class="actions-cell">
|
|
18
18
|
<% if paused %>
|
|
19
19
|
<form action="<%= resume_queue_path %>" method="post" class="inline-form">
|
|
20
|
+
<%= csrf_token_field_if_enabled %>
|
|
20
21
|
<input type="hidden" name="queue_name" value="<%= queue_name %>">
|
|
21
22
|
<button type="submit" class="action-button resume-button" title="Resume queue processing">Resume</button>
|
|
22
23
|
</form>
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
method="post"
|
|
26
27
|
class="inline-form"
|
|
27
28
|
data-confirm="Are you sure you want to pause the <%= queue_name %> queue? Workers will stop processing jobs from this queue.">
|
|
29
|
+
<%= csrf_token_field_if_enabled %>
|
|
28
30
|
<input type="hidden" name="queue_name" value="<%= queue_name %>">
|
|
29
31
|
<button type="submit" class="action-button pause-button" title="Pause queue processing">Pause</button>
|
|
30
32
|
</form>
|
|
@@ -11,12 +11,14 @@
|
|
|
11
11
|
<div class="section-header-right">
|
|
12
12
|
<% if @paused %>
|
|
13
13
|
<form action="<%= resume_queue_path %>" method="post" class="inline-form">
|
|
14
|
+
<%= csrf_token_field_if_enabled %>
|
|
14
15
|
<input type="hidden" name="queue_name" value="<%= @queue_name %>">
|
|
15
16
|
<input type="hidden" name="redirect_to" value="<%= queue_details_path(queue_name: @queue_name) %>">
|
|
16
17
|
<button type="submit" class="action-button resume-button">Resume Queue</button>
|
|
17
18
|
</form>
|
|
18
19
|
<% else %>
|
|
19
20
|
<form action="<%= pause_queue_path %>" method="post" class="inline-form" data-confirm="Are you sure you want to pause this queue?">
|
|
21
|
+
<%= csrf_token_field_if_enabled %>
|
|
20
22
|
<input type="hidden" name="queue_name" value="<%= @queue_name %>">
|
|
21
23
|
<input type="hidden" name="redirect_to" value="<%= queue_details_path(queue_name: @queue_name) %>">
|
|
22
24
|
<button type="submit" class="action-button pause-button">Pause Queue</button>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
method="post"
|
|
14
14
|
class="inline-form"
|
|
15
15
|
data-confirm="Remove this dead process from the registry?">
|
|
16
|
+
<%= csrf_token_field_if_enabled %>
|
|
16
17
|
<button type="submit" class="action-button discard-button" title="Remove dead process">Remove</button>
|
|
17
18
|
</form>
|
|
18
19
|
<% else %>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
data-confirm="Remove all <%= @summary[:dead] %> dead process<%= suffix %>? This will clean up processes that have stopped sending heartbeats.">
|
|
25
25
|
Prune all
|
|
26
26
|
</a>
|
|
27
|
-
<form id="prune-all-form" action="<%= prune_workers_path %>" method="post" class="is-hidden"
|
|
27
|
+
<form id="prune-all-form" action="<%= prune_workers_path %>" method="post" class="is-hidden"><%= csrf_token_field_if_enabled %></form>
|
|
28
28
|
<% end %>
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
@@ -27,4 +27,11 @@ SolidQueueMonitor.setup do |config|
|
|
|
27
27
|
|
|
28
28
|
# Disable the chart on the overview page to skip chart queries entirely.
|
|
29
29
|
# config.show_chart = true
|
|
30
|
+
|
|
31
|
+
# Enable CSRF protection for the dashboard's destructive POST actions.
|
|
32
|
+
# Disabled by default for backward compatibility. Requires the host app to
|
|
33
|
+
# have a session store (e.g. cookie_store) and the dashboard mounted on the
|
|
34
|
+
# same origin. When enabled, all dashboard forms embed an authenticity token
|
|
35
|
+
# and unverified POSTs are rejected.
|
|
36
|
+
# config.csrf_protection_enabled = false
|
|
30
37
|
end
|
data/lib/solid_queue_monitor.rb
CHANGED
|
@@ -5,10 +5,14 @@ require_relative 'solid_queue_monitor/engine'
|
|
|
5
5
|
|
|
6
6
|
module SolidQueueMonitor
|
|
7
7
|
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
DEFAULT_BASE_CONTROLLER_CLASS = 'ActionController::Base'
|
|
10
|
+
|
|
8
11
|
class << self
|
|
9
|
-
attr_writer :username, :password
|
|
12
|
+
attr_writer :username, :password, :base_controller_class
|
|
10
13
|
attr_accessor :jobs_per_page, :authentication_enabled,
|
|
11
|
-
:auto_refresh_enabled, :auto_refresh_interval, :show_chart
|
|
14
|
+
:auto_refresh_enabled, :auto_refresh_interval, :show_chart,
|
|
15
|
+
:csrf_protection_enabled
|
|
12
16
|
|
|
13
17
|
def username
|
|
14
18
|
resolve_value(@username)
|
|
@@ -18,6 +22,10 @@ module SolidQueueMonitor
|
|
|
18
22
|
resolve_value(@password)
|
|
19
23
|
end
|
|
20
24
|
|
|
25
|
+
def base_controller_class
|
|
26
|
+
@base_controller_class || DEFAULT_BASE_CONTROLLER_CLASS
|
|
27
|
+
end
|
|
28
|
+
|
|
21
29
|
private
|
|
22
30
|
|
|
23
31
|
def resolve_value(value)
|
|
@@ -32,6 +40,9 @@ module SolidQueueMonitor
|
|
|
32
40
|
@auto_refresh_enabled = true
|
|
33
41
|
@auto_refresh_interval = 30 # seconds
|
|
34
42
|
@show_chart = true
|
|
43
|
+
# Disabled by default for backward compatibility: enabling CSRF protection
|
|
44
|
+
# requires a session-backed host app, which the gem does not assume.
|
|
45
|
+
@csrf_protection_enabled = false
|
|
35
46
|
|
|
36
47
|
def self.setup
|
|
37
48
|
yield self
|