i18n_feedback 0.1.0 → 0.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/CHANGELOG.md +6 -0
- data/README.md +2 -2
- data/app/helpers/i18n_feedback/tag_helper.rb +2 -1
- data/lib/i18n_feedback/middleware.rb +15 -3
- data/lib/i18n_feedback/version.rb +1 -1
- data/lib/i18n_feedback/widget.rb +7 -4
- 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: ab6f3f1bb7c4568e3491627e947cf38424ec76f0c21cff477bee95440c4df762
|
|
4
|
+
data.tar.gz: 8440049b960f561014f0217caf61395de948a0f665dc580b39e97f07bc55dddf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0cafcd664c77f1f39c1a2029fe3f22d3e8d3dc3753c40a3d087a31d3b11c7bedaa73d2e22ddcc4abf9106a45510dcc63f2b287874555d439f536e09f7018c6f
|
|
7
|
+
data.tar.gz: d402186abbb1c9437feee55e52110ddb11b82332f29d7d3443524b204eaa2a30dff4691ef2edcae7a28cfc71bae80eabd0b2b62283c0224167ddaaf9c02cefe6
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.2.0]
|
|
6
|
+
|
|
7
|
+
- Stamp the injected widget scripts with the request's Content-Security-Policy
|
|
8
|
+
nonce when one is present, so the tool works under a nonce-based CSP (including
|
|
9
|
+
`strict-dynamic`). No-op for apps without a CSP nonce.
|
|
10
|
+
|
|
5
11
|
## [0.1.0]
|
|
6
12
|
|
|
7
13
|
- Initial release.
|
data/README.md
CHANGED
|
@@ -35,11 +35,11 @@ It is meant for development and staging, never production.
|
|
|
35
35
|
|
|
36
36
|
## Installation
|
|
37
37
|
|
|
38
|
-
Add the gem
|
|
38
|
+
Add the gem:
|
|
39
39
|
|
|
40
40
|
```ruby
|
|
41
41
|
# Gemfile
|
|
42
|
-
gem "i18n_feedback"
|
|
42
|
+
gem "i18n_feedback"
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
```bash
|
|
@@ -11,7 +11,8 @@ module I18nFeedback
|
|
|
11
11
|
Widget.snippet(
|
|
12
12
|
endpoint: I18nFeedback.config.suggestions_endpoint,
|
|
13
13
|
locale: I18n.locale,
|
|
14
|
-
active: I18nFeedback::Marking.enabled
|
|
14
|
+
active: I18nFeedback::Marking.enabled?,
|
|
15
|
+
nonce: (content_security_policy_nonce if respond_to?(:content_security_policy_nonce))
|
|
15
16
|
).html_safe
|
|
16
17
|
end
|
|
17
18
|
end
|
|
@@ -30,7 +30,7 @@ module I18nFeedback
|
|
|
30
30
|
headers = persist_choice(headers, override) if available && !override.nil?
|
|
31
31
|
|
|
32
32
|
if available && I18nFeedback.config.auto_inject && html?(headers) && !request.xhr?
|
|
33
|
-
status, headers, body = inject(status, headers, body, marking)
|
|
33
|
+
status, headers, body = inject(status, headers, body, marking, csp_nonce(env))
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
[status, headers, body]
|
|
@@ -44,6 +44,17 @@ module I18nFeedback
|
|
|
44
44
|
!request.cookies[COOKIE].to_s.empty?
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
# The request's CSP nonce, so the injected scripts run under a nonce-based
|
|
48
|
+
# Content-Security-Policy. Reads the value Rails memoizes on the env, which is
|
|
49
|
+
# the same nonce the CSP header uses. nil when the app sets no nonce.
|
|
50
|
+
def csp_nonce(env)
|
|
51
|
+
return nil unless defined?(ActionDispatch::Request)
|
|
52
|
+
|
|
53
|
+
ActionDispatch::Request.new(env).content_security_policy_nonce
|
|
54
|
+
rescue StandardError
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
47
58
|
def toggle_override(request)
|
|
48
59
|
param = I18nFeedback.config.toggle_param
|
|
49
60
|
return nil unless request.params.key?(param)
|
|
@@ -80,7 +91,7 @@ module I18nFeedback
|
|
|
80
91
|
headers['Content-Type'] || headers['content-type']
|
|
81
92
|
end
|
|
82
93
|
|
|
83
|
-
def inject(status, headers, body, marking)
|
|
94
|
+
def inject(status, headers, body, marking, nonce)
|
|
84
95
|
html = +''
|
|
85
96
|
body.each { |part| html << part.to_s }
|
|
86
97
|
body.close if body.respond_to?(:close)
|
|
@@ -88,7 +99,8 @@ module I18nFeedback
|
|
|
88
99
|
snippet = Widget.snippet(
|
|
89
100
|
endpoint: I18nFeedback.config.suggestions_endpoint,
|
|
90
101
|
locale: I18n.locale,
|
|
91
|
-
active: marking
|
|
102
|
+
active: marking,
|
|
103
|
+
nonce: nonce
|
|
92
104
|
)
|
|
93
105
|
html = html.include?('</body>') ? html.sub('</body>', "#{snippet}</body>") : html + snippet
|
|
94
106
|
|
data/lib/i18n_feedback/widget.rb
CHANGED
|
@@ -17,8 +17,10 @@ module I18nFeedback
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# The two <script> tags to place before </body>: one carrying the runtime
|
|
20
|
-
# config, one carrying the widget itself.
|
|
21
|
-
|
|
20
|
+
# config, one carrying the widget itself. `nonce:` stamps both tags so the
|
|
21
|
+
# widget runs under a nonce-based Content-Security-Policy (e.g. one using
|
|
22
|
+
# 'strict-dynamic'); pass nil when the app has no CSP nonce.
|
|
23
|
+
def snippet(endpoint:, locale:, active:, nonce: nil)
|
|
22
24
|
config = {
|
|
23
25
|
endpoint: endpoint,
|
|
24
26
|
locale: locale.to_s,
|
|
@@ -26,9 +28,10 @@ module I18nFeedback
|
|
|
26
28
|
showPill: I18nFeedback.config.show_pill ? true : false,
|
|
27
29
|
pillLabel: I18nFeedback.config.pill_label
|
|
28
30
|
}
|
|
31
|
+
nonce_attr = nonce ? %( nonce="#{nonce}") : ''
|
|
29
32
|
|
|
30
|
-
%(<script data-i18n-feedback>window.__i18nFeedback=#{config.to_json};</script>) +
|
|
31
|
-
%(<script data-i18n-feedback-widget>#{javascript}</script>)
|
|
33
|
+
%(<script data-i18n-feedback#{nonce_attr}>window.__i18nFeedback=#{config.to_json};</script>) +
|
|
34
|
+
%(<script data-i18n-feedback-widget#{nonce_attr}>#{javascript}</script>)
|
|
32
35
|
end
|
|
33
36
|
end
|
|
34
37
|
end
|