rails_error_dashboard 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/rails_error_dashboard/application_controller.rb +53 -0
- data/app/controllers/rails_error_dashboard/errors_controller.rb +4 -0
- data/app/views/rails_error_dashboard/errors/rack_attack_summary.html.erb +15 -5
- data/app/views/rails_error_dashboard/errors/settings.html.erb +1 -1
- data/lib/rails_error_dashboard/configuration.rb +16 -0
- data/lib/rails_error_dashboard/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba282b251af897146a14dce9cbd14aae0032428b96bb8d274d7400db3b1386cd
|
|
4
|
+
data.tar.gz: 4d4de4a7d143fe4233ea283766f452018f0a057652620077579686c6a10b1cbe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e794d0737d5c8381a8a127ff30ebea8023fbf3e9b73f089d2cde9832617f953a6a589481a954dad41e1a18c85400e36e3a04a8a3bac35eaedc35aa53cf3a3d87
|
|
7
|
+
data.tar.gz: b9cff40ccba8d4459e0fe829dbf43fd054c66ff3f2a28a15d0be334e84fe757fc02c1d34e326ab1956a5d6074474113951e42bfdd9f9ef43705a0cfae46c0165
|
|
@@ -12,6 +12,16 @@ module RailsErrorDashboard
|
|
|
12
12
|
|
|
13
13
|
protect_from_forgery with: :exception
|
|
14
14
|
|
|
15
|
+
# Render pagination in the dashboard's own locale, not the host app's.
|
|
16
|
+
#
|
|
17
|
+
# Pagy stores its locale in Thread.current[:pagy_locale] and never resets it
|
|
18
|
+
# (pagy 43.6.1, modules/i18n/i18n.rb:24-31 — the "for the duration of a single
|
|
19
|
+
# request" comment is aspirational; nothing in the gem enforces it). A host app
|
|
20
|
+
# that sets a per-request locale leaves that value on the Puma thread, so a
|
|
21
|
+
# dashboard request landing on a recycled thread inherits whatever language the
|
|
22
|
+
# host last used — Russian on one refresh, Portuguese on the next (issue #148).
|
|
23
|
+
around_action :with_dashboard_locale
|
|
24
|
+
|
|
15
25
|
# CRITICAL: Ensure dashboard errors never break the app
|
|
16
26
|
# Catch all exceptions and render user-friendly error page
|
|
17
27
|
# NOTE: rescue_from is checked in reverse declaration order (last = highest priority).
|
|
@@ -60,6 +70,49 @@ module RailsErrorDashboard
|
|
|
60
70
|
|
|
61
71
|
private
|
|
62
72
|
|
|
73
|
+
# Set Pagy's locale for this request and restore whatever was there before.
|
|
74
|
+
#
|
|
75
|
+
# Two details are load-bearing:
|
|
76
|
+
#
|
|
77
|
+
# 1. The previous value is read from Thread.current directly, NOT from
|
|
78
|
+
# Pagy::I18n.locale. The getter coerces nil to "en", so restoring through
|
|
79
|
+
# it would stamp "en" onto a thread that started clean — making the
|
|
80
|
+
# dashboard a source of the very leak it is fixing.
|
|
81
|
+
# 2. around_action + ensure, not before_action. A before_action would strand
|
|
82
|
+
# the dashboard's locale on the thread for the host app's next request.
|
|
83
|
+
# The ensure also covers the rescue_from handlers above, which still
|
|
84
|
+
# render through the view layer.
|
|
85
|
+
def with_dashboard_locale
|
|
86
|
+
previous = Thread.current[:pagy_locale]
|
|
87
|
+
Pagy::I18n.locale = dashboard_pagy_locale
|
|
88
|
+
yield
|
|
89
|
+
ensure
|
|
90
|
+
Thread.current[:pagy_locale] = previous
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def dashboard_pagy_locale
|
|
94
|
+
configured = RailsErrorDashboard.configuration.dashboard_locale.to_s.strip
|
|
95
|
+
return "en" if configured.empty?
|
|
96
|
+
|
|
97
|
+
self.class.resolved_pagy_locales[configured] ||= resolve_pagy_locale(configured)
|
|
98
|
+
rescue StandardError
|
|
99
|
+
"en"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Pagy looks its dictionary up by exact filename AND by an exact top-level
|
|
103
|
+
# key inside that YAML, so "EN" finds en.yml but then reads a nil dictionary
|
|
104
|
+
# and raises mid-render. Match the shipped filenames case-insensitively and
|
|
105
|
+
# fall back to English for anything Pagy cannot serve.
|
|
106
|
+
def resolve_pagy_locale(configured)
|
|
107
|
+
available = Pagy::I18n.pathnames.flat_map { |dir| Dir.glob(dir.join("*.yml")) }
|
|
108
|
+
.map { |path| File.basename(path, ".yml") }
|
|
109
|
+
available.find { |locale| locale.casecmp?(configured) } || "en"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def self.resolved_pagy_locales
|
|
113
|
+
@resolved_pagy_locales ||= {}
|
|
114
|
+
end
|
|
115
|
+
|
|
63
116
|
def render_dashboard_error(icon:, title:, message:, detail: nil, icon_style: nil, status: :internal_server_error)
|
|
64
117
|
set_common_view_variables
|
|
65
118
|
error_html = <<~ERB
|
|
@@ -490,6 +490,10 @@ module RailsErrorDashboard
|
|
|
490
490
|
return
|
|
491
491
|
end
|
|
492
492
|
|
|
493
|
+
# Distinguishes "gem not installed" from "installed but no rules matched"
|
|
494
|
+
# in the empty state — both otherwise render an identical blank page.
|
|
495
|
+
@rack_attack_missing = !defined?(::Rack::Attack)
|
|
496
|
+
|
|
493
497
|
days = days_param(default: 30)
|
|
494
498
|
@days = days
|
|
495
499
|
result = Queries::RackAttackSummary.call(days, application_id: @current_application_id)
|
|
@@ -22,11 +22,21 @@
|
|
|
22
22
|
|
|
23
23
|
<% if @unique_rules == 0 %>
|
|
24
24
|
<div class="red-empty-state">
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
<% if @rack_attack_missing %>
|
|
26
|
+
<i class="bi bi-exclamation-triangle display-1 text-warning mb-3"></i>
|
|
27
|
+
<div class="red-empty-state-title">Rack Attack Is Not Installed</div>
|
|
28
|
+
<p class="text-muted">
|
|
29
|
+
Tracking is enabled, but the <code>rack-attack</code> gem is not loaded in this
|
|
30
|
+
application — so no events can be recorded. Add it to your Gemfile and configure
|
|
31
|
+
at least one rule, then events will appear here.
|
|
32
|
+
</p>
|
|
33
|
+
<% else %>
|
|
34
|
+
<i class="bi bi-shield-check display-1 text-success mb-3"></i>
|
|
35
|
+
<div class="red-empty-state-title">No Rate Limit Events Found</div>
|
|
36
|
+
<p class="text-muted">
|
|
37
|
+
No Rack Attack throttle, blocklist, or track events were recorded over the last <%= @days %> days.
|
|
38
|
+
</p>
|
|
39
|
+
<% end %>
|
|
30
40
|
<div class="card mx-auto" style="max-width: 500px;">
|
|
31
41
|
<div class="card-body text-start">
|
|
32
42
|
<h6>How Rack Attack tracking works:</h6>
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
icon: "bi-broadcast",
|
|
145
145
|
color: "info",
|
|
146
146
|
settings: {
|
|
147
|
-
enable_rack_attack_tracking: { label: "Rack Attack Tracking", description: "
|
|
147
|
+
enable_rack_attack_tracking: { label: "Rack Attack Tracking", description: "Record throttle/blocklist events to their own table", type: :boolean },
|
|
148
148
|
enable_actioncable_tracking: { label: "ActionCable Tracking", description: "Track WebSocket channel events as breadcrumbs", type: :boolean },
|
|
149
149
|
enable_activestorage_tracking: { label: "ActiveStorage Tracking", description: "Track uploads/downloads/deletes as breadcrumbs", type: :boolean }
|
|
150
150
|
}
|
|
@@ -222,6 +222,11 @@ module RailsErrorDashboard
|
|
|
222
222
|
# Dashboard UI appearance
|
|
223
223
|
attr_accessor :accent_color # :crimson (default), :ruby, :ember, :violet
|
|
224
224
|
|
|
225
|
+
# Locale the dashboard renders in, independent of the host app's locale.
|
|
226
|
+
# Currently applies to Pagy pagination labels — the rest of the dashboard
|
|
227
|
+
# UI is not yet translated (default: "en").
|
|
228
|
+
attr_accessor :dashboard_locale
|
|
229
|
+
|
|
225
230
|
# LLM-powered AI help (disabled unless provider and API key are configured)
|
|
226
231
|
attr_accessor :llm_provider # :openai or :anthropic
|
|
227
232
|
attr_accessor :llm_api_key # String or lambda/proc
|
|
@@ -433,6 +438,7 @@ module RailsErrorDashboard
|
|
|
433
438
|
|
|
434
439
|
# Dashboard UI
|
|
435
440
|
@accent_color = :crimson # :crimson, :ruby, :ember, :violet
|
|
441
|
+
@dashboard_locale = "en" # Pagy pagination labels; rest of the UI is English-only
|
|
436
442
|
|
|
437
443
|
# LLM-powered AI help defaults - OFF until provider and API key are configured
|
|
438
444
|
@llm_provider = ENV["RED_LLM_PROVIDER"]&.to_sym
|
|
@@ -590,6 +596,16 @@ module RailsErrorDashboard
|
|
|
590
596
|
if rack_attack_flush_interval && rack_attack_flush_interval < 1
|
|
591
597
|
errors << "rack_attack_flush_interval must be at least 1 (got: #{rack_attack_flush_interval})"
|
|
592
598
|
end
|
|
599
|
+
|
|
600
|
+
# Warn rather than auto-disable: validation may run before the host's
|
|
601
|
+
# Rack::Attack initializer has loaded, so a missing constant here does
|
|
602
|
+
# not prove it will still be missing at after_initialize (when the
|
|
603
|
+
# subscriber actually registers). Auto-disabling would break that case.
|
|
604
|
+
unless defined?(::Rack::Attack)
|
|
605
|
+
warnings << "enable_rack_attack_tracking is enabled but the rack-attack gem " \
|
|
606
|
+
"does not appear to be loaded. No events will be recorded until " \
|
|
607
|
+
"Rack::Attack is installed and configured."
|
|
608
|
+
end
|
|
593
609
|
end
|
|
594
610
|
|
|
595
611
|
# Validate actioncable tracking requires breadcrumbs
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_error_dashboard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anjan Jagirdar
|
|
@@ -530,7 +530,7 @@ metadata:
|
|
|
530
530
|
funding_uri: https://github.com/sponsors/AnjanJ
|
|
531
531
|
post_install_message: |
|
|
532
532
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
533
|
-
RED (Rails Error Dashboard) v0.8.
|
|
533
|
+
RED (Rails Error Dashboard) v0.8.4
|
|
534
534
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
535
535
|
|
|
536
536
|
First install:
|