bullet 8.0.4 → 8.0.6
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/CHANGELOG.md +11 -1
- data/README.md +2 -0
- data/lib/bullet/rack.rb +41 -33
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +7 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f00b664af513340b8b094dfa967a2dbd2c3a72edfcb0031532dd4ba38a1fb4b2
|
4
|
+
data.tar.gz: 76b42f07c889542a50cc75a52d52fef26bf8647721d3c9913eb4f1dbb21db9a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db329cba6757c1ec372a7a7b6a8a9aa4a92fd5c63ce1a0e92cd43c89abd852768a83eddd95873a1cdeb2155abfa899d4c385df2a670b326c3eaa8736398a996e
|
7
|
+
data.tar.gz: 35c6df4a0e0aefd934c1038f2dc5faa7978cbe7b81e482ea0ca931045d4b445a67d33d0c69d603830111cee46f9bf5128a9824277de7ef3dc347c10eae5d84ea
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
## Next Release
|
2
2
|
|
3
|
-
## 8.0.
|
3
|
+
## 8.0.6 (05/07/2025)
|
4
|
+
|
5
|
+
* Add CSP nonce for footer styles as well
|
6
|
+
* Add support for OpenTelemetry reporting
|
7
|
+
|
8
|
+
## 8.0.5 (04/21/2025)
|
9
|
+
|
10
|
+
* Properly insert ContentSecurityPolicy middleware
|
11
|
+
* Properly parse query string
|
12
|
+
|
13
|
+
## 8.0.4 (04/18/2025)
|
4
14
|
|
5
15
|
* Insert bullet middleware before `ContentSecurityPolicy`
|
6
16
|
* Support url query `skip_html_injection=true`
|
data/README.md
CHANGED
@@ -74,6 +74,7 @@ config.after_initialize do
|
|
74
74
|
Bullet.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
|
75
75
|
Bullet.stacktrace_excludes = [ 'their_gem', 'their_middleware', ['my_file.rb', 'my_method'], ['my_file.rb', 16..20] ]
|
76
76
|
Bullet.slack = { webhook_url: 'http://some.slack.url', channel: '#default', username: 'notifier' }
|
77
|
+
Bullet.opentelemetry = true
|
77
78
|
end
|
78
79
|
```
|
79
80
|
|
@@ -100,6 +101,7 @@ The code above will enable all of the Bullet notification systems:
|
|
100
101
|
Each item can be a string (match substring), a regex, or an array where the first item is a path to match, and the second
|
101
102
|
item is a line number, a Range of line numbers, or a (bare) method name, to exclude only particular lines in a file.
|
102
103
|
* `Bullet.slack`: add notifications to slack
|
104
|
+
* `Bullet.opentelemetry`: add notifications to OpenTelemetry
|
103
105
|
* `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
|
104
106
|
* `Bullet.always_append_html_body`: always append the html body even if no notifications are present. Note: `console` or `add_footer` must also be true. Useful for Single Page Applications where the initial page load might not have any notifications present.
|
105
107
|
* `Bullet.skip_user_in_notification`: exclude the OS user (`whoami`) from notifications.
|
data/lib/bullet/rack.rb
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'rack/request'
|
4
4
|
require 'json'
|
5
|
+
require 'cgi'
|
5
6
|
|
6
7
|
module Bullet
|
7
8
|
class Rack
|
8
9
|
include Dependency
|
9
10
|
|
10
|
-
NONCE_MATCHER = /script-src .*'nonce-(?<nonce>[A-Za-z0-9+\/]+={0,2})'/
|
11
|
+
NONCE_MATCHER = /(script|style)-src .*'nonce-(?<nonce>[A-Za-z0-9+\/]+={0,2})'/
|
11
12
|
|
12
13
|
def initialize(app)
|
13
14
|
@app = app
|
@@ -28,7 +29,7 @@ module Bullet
|
|
28
29
|
response_body = response_body(response)
|
29
30
|
|
30
31
|
with_security_policy_nonce(headers) do |nonce|
|
31
|
-
response_body = append_to_html_body(response_body, footer_note) if Bullet.add_footer
|
32
|
+
response_body = append_to_html_body(response_body, footer_note(nonce)) if Bullet.add_footer
|
32
33
|
response_body = append_to_html_body(response_body, Bullet.gather_inline_notifications)
|
33
34
|
if Bullet.add_footer && !Bullet.skip_http_headers
|
34
35
|
response_body = append_to_html_body(response_body, xhr_script(nonce))
|
@@ -69,8 +70,22 @@ module Bullet
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
72
|
-
def footer_note
|
73
|
-
|
73
|
+
def footer_note(nonce = nil)
|
74
|
+
%(<details id="bullet-footer" data-is-bullet-footer><summary>Bullet Warnings</summary><div>#{Bullet.footer_info.uniq.join('<br>')}#{footer_console_message(nonce)}</div>#{footer_style(nonce)}</details>)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Make footer styles work with ContentSecurityPolicy style-src as self
|
78
|
+
def footer_style(nonce = nil)
|
79
|
+
css = <<~CSS
|
80
|
+
details#bullet-footer {cursor: pointer; position: fixed; left: 0px; bottom: 0px; z-index: 9999; background: #fdf2f2; color: #9b1c1c; font-size: 12px; border-radius: 0px 8px 0px 0px; border: 1px solid #9b1c1c;}
|
81
|
+
details#bullet-footer summary {font-weight: 600; padding: 2px 8px;}
|
82
|
+
details#bullet-footer div {padding: 8px; border-top: 1px solid #9b1c1c;}
|
83
|
+
CSS
|
84
|
+
if nonce
|
85
|
+
%(<style type="text/css" nonce="#{nonce}">#{css}</style>)
|
86
|
+
else
|
87
|
+
%(<style type="text/css">#{css}</style>)
|
88
|
+
end
|
74
89
|
end
|
75
90
|
|
76
91
|
def set_header(headers, header_name, header_array)
|
@@ -85,17 +100,20 @@ module Bullet
|
|
85
100
|
query_string = request.env['QUERY_STRING']
|
86
101
|
return false if query_string.nil? || query_string.empty?
|
87
102
|
|
88
|
-
|
89
|
-
parser = Rack::QueryParser.new
|
90
|
-
params = parser.parse_nested_query(query_string)
|
91
|
-
else
|
92
|
-
# compatible with rack 1.x,
|
93
|
-
# remove it after dropping rails 4.2 suppport
|
94
|
-
params = Rack::Utils.parse_nested_query(query_string)
|
95
|
-
end
|
103
|
+
params = simple_parse_query_string(query_string)
|
96
104
|
params['skip_html_injection'] == 'true'
|
97
105
|
end
|
98
106
|
|
107
|
+
# Simple query string parser
|
108
|
+
def simple_parse_query_string(query_string)
|
109
|
+
params = {}
|
110
|
+
query_string.split('&').each do |pair|
|
111
|
+
key, value = pair.split('=', 2).map { |s| CGI.unescape(s) }
|
112
|
+
params[key] = value if key && !key.empty?
|
113
|
+
end
|
114
|
+
params
|
115
|
+
end
|
116
|
+
|
99
117
|
def file?(headers)
|
100
118
|
headers['Content-Transfer-Encoding'] == 'binary' || headers['Content-Disposition']
|
101
119
|
end
|
@@ -118,28 +136,18 @@ module Bullet
|
|
118
136
|
|
119
137
|
private
|
120
138
|
|
121
|
-
def
|
122
|
-
<<~EOF
|
123
|
-
id="bullet-footer" data-is-bullet-footer
|
124
|
-
style="cursor: pointer; position: fixed; left: 0px; bottom: 0px; z-index: 9999; background: #fdf2f2; color: #9b1c1c; font-size: 12px; border-radius: 0px 8px 0px 0px; border: 1px solid #9b1c1c;"
|
125
|
-
EOF
|
126
|
-
end
|
127
|
-
|
128
|
-
def summary_attributes
|
129
|
-
<<~EOF
|
130
|
-
style="font-weight: 600; padding: 2px 8px"
|
131
|
-
EOF
|
132
|
-
end
|
133
|
-
|
134
|
-
def footer_content_attributes
|
135
|
-
<<~EOF
|
136
|
-
style="padding: 8px; border-top: 1px solid #9b1c1c;"
|
137
|
-
EOF
|
138
|
-
end
|
139
|
-
|
140
|
-
def footer_console_message
|
139
|
+
def footer_console_message(nonce = nil)
|
141
140
|
if Bullet.console_enabled?
|
142
|
-
|
141
|
+
footer = %(<br/><span id="console-message">See 'Uniform Notifier' in JS Console for Stacktrace</span>)
|
142
|
+
css = "details#bullet-footer #console-message {font-style: italic;}"
|
143
|
+
style =
|
144
|
+
if nonce
|
145
|
+
%(<style type="text/css" nonce="#{nonce}">#{css}</style>)
|
146
|
+
else
|
147
|
+
%(<style type="text/css">#{css}</style>)
|
148
|
+
end
|
149
|
+
|
150
|
+
footer + style
|
143
151
|
end
|
144
152
|
end
|
145
153
|
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
@@ -23,11 +23,14 @@ module Bullet
|
|
23
23
|
|
24
24
|
if defined?(Rails::Railtie)
|
25
25
|
class BulletRailtie < Rails::Railtie
|
26
|
-
initializer 'bullet.
|
27
|
-
if
|
28
|
-
|
29
|
-
|
26
|
+
initializer 'bullet.add_middleware' do |app|
|
27
|
+
# I don't find a way to detect if the middleware is already in the stack,
|
28
|
+
# so I'm using the api_only flag.
|
29
|
+
# If it is true, ActionDispatch::ContentSecurityPolicy::Middleware is not in the stack.
|
30
|
+
if app.config.api_only || !defined?(ActionDispatch::ContentSecurityPolicy::Middleware)
|
30
31
|
app.middleware.use Bullet::Rack
|
32
|
+
else
|
33
|
+
app.middleware.insert_before ActionDispatch::ContentSecurityPolicy::Middleware, Bullet::Rack
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.0.
|
4
|
+
version: 8.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activesupport
|
@@ -112,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: 1.3.6
|
114
114
|
requirements: []
|
115
|
-
rubygems_version: 3.6.
|
115
|
+
rubygems_version: 3.6.7
|
116
116
|
specification_version: 4
|
117
117
|
summary: help to kill N+1 queries and unused eager loading.
|
118
118
|
test_files: []
|