cloudflare-turnstile-rails 1.0.2 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 196412eb6b781fae101b937a9f76b0aa5eaebf94be239466cf3a9edc3175356b
4
- data.tar.gz: 4077e06435e1c39254bd4b74aee2eaa7cb219cea37d8cbef8c37998e50f0075a
3
+ metadata.gz: 7a86ed02899dc2410a686143de9c188b3d15cfef8e4928bc87cc00bd1741fb58
4
+ data.tar.gz: 566026c1569d205f3a91beec381ec29729e6afe78084b9a6fb60ef4ceb0b3fad
5
5
  SHA512:
6
- metadata.gz: 3e28b314dc36c83eaf191ecbe6a47e2477a7c80a54e7d791b5a3ee0d07c6f6617fbd3f06bb822c15cba75e3637b963c6524b40473eaa399932543f649abb85f1
7
- data.tar.gz: d28f2f512b7efc7bd387e410e6829053c6a7019d730b3fb7dfa5bd69d87c59dab7dd0816187a621d7c80533c67931ce3511bca42266804f39e15f4ad77368e7d
6
+ metadata.gz: 5a5a699a90fcb1a704de8a46ec57571c5219794d853d94a0d7bbac05e3e91dfa7ee20ddefaa1245d246a8b64bba082f58800821db4e2d4accc3ac16252eca204
7
+ data.tar.gz: e3655f9b725839b328f3699fd7dfb8def8f91d8011bd10dd4c8e4904cc6a12c61453a85bde4c666cd8d26185cb623da406ec634828785ff27d5833b6e5854594
data/README.md CHANGED
@@ -1,20 +1,22 @@
1
1
  # Cloudflare Turnstile Rails
2
2
 
3
- [![Gem Version](https://img.shields.io/gem/v/cloudflare-turnstile-rails.svg)](https://rubygems.org/gems/cloudflare-turnstile-rails)
4
- [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
- [![Lint Status](https://github.com/vkononov/cloudflare-turnstile-rails/actions/workflows/lint.yml/badge.svg)](https://github.com/vkononov/cloudflare-turnstile-rails/actions/workflows/lint.yml)
6
- [![Test Status](https://github.com/vkononov/cloudflare-turnstile-rails/actions/workflows/test.yml/badge.svg)](https://github.com/vkononov/cloudflare-turnstile-rails/actions/workflows/test.yml)
3
+ [![Gem Version](https://img.shields.io/gem/v/cloudflare-turnstile-rails.svg?label=Gem&logo=rubygems&logoColor=white)](https://rubygems.org/gems/cloudflare-turnstile-rails)
4
+ [![Ruby](https://img.shields.io/badge/Ruby-2.6%20to%204.0-CC342D?logo=ruby&logoColor=white)](https://github.com/vkononov/cloudflare-turnstile-rails/blob/main/.github/workflows/test.yml)
5
+ [![Rails](https://img.shields.io/badge/Rails-5.0%20to%208.1-D30001?logo=rubyonrails&logoColor=white)](https://github.com/vkononov/cloudflare-turnstile-rails/blob/main/Appraisals)
6
+ [![Test Matrix](https://img.shields.io/github/actions/workflow/status/vkononov/cloudflare-turnstile-rails/test.yml?branch=main&label=Test%20Matrix&logo=github)](https://github.com/vkononov/cloudflare-turnstile-rails/actions/workflows/test.yml)
7
+ [![Lint](https://img.shields.io/github/actions/workflow/status/vkononov/cloudflare-turnstile-rails/lint.yml?branch=main&label=Lint&logo=github)](https://github.com/vkononov/cloudflare-turnstile-rails/actions/workflows/lint.yml)
8
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/license/MIT)
7
9
 
8
10
  Cloudflare Turnstile gem for Ruby on Rails with built-in Turbo and Turbolinks support and CSP compliance.
9
11
 
10
- Supports `Rails >= 5.0` with `Ruby >= 2.6.0`.
12
+ Supports **Rails 5.0 latest** and **Ruby 2.6 → latest**, with the full Rails/Ruby matrix tested daily in CI.
11
13
 
12
14
  [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/vkononov)
13
15
 
14
16
  ## Features
15
17
 
16
18
  * **One‑line integration**: `<%= cloudflare_turnstile_tag %>` in views, `valid_turnstile?(model:)` in controllers — no extra wiring.
17
- * **Turbo & Turbo Streams aware**: Automatically re‑initializes widgets on `turbo:load`, `turbo:before-stream-render`, and DOM mutations.
19
+ * **Turbo & Turbo Streams aware**: Automatically re‑initializes widgets on `turbo:render` and `turbo:before-stream-render`.
18
20
  * **Legacy Turbolinks support**: Includes a helper for Turbolinks to handle remote form submissions with validation errors.
19
21
  * **CSP nonce support**: Honours Rails' `content_security_policy_nonce` for secure inline scripts.
20
22
  * **Rails Engine & Asset pipeline**: Ships a precompiled JS helper via Railtie — no manual asset setup.
@@ -87,10 +89,35 @@ Supports `Rails >= 5.0` with `Ruby >= 2.6.0`.
87
89
  <%= cloudflare_turnstile_tag %>
88
90
  ```
89
91
 
90
- That's it! Though it is recommended to match your `theme` and `language` to your app's design and locale:
92
+ That's it! By default the widget auto-detects the visitor's `theme` and `language`.
93
+
94
+ * To match your app's design and locale, set defaults once in the initializer and they'll apply to every `cloudflare_turnstile_tag` automatically:
95
+
96
+ ```ruby
97
+ Cloudflare::Turnstile::Rails.configure do |config|
98
+ config.default_data = {
99
+ theme: 'light',
100
+ language: 'en'
101
+ }
102
+ end
103
+ ```
104
+
105
+ Values may also be a proc, evaluated at render time — useful for following the current locale:
106
+
107
+ ```ruby
108
+ config.default_data = { language: -> { I18n.locale } }
109
+ ```
110
+
111
+ * You can still override any default (or add extra options) on an individual tag via the `data:` option. Per-tag values take precedence over the configured defaults:
91
112
 
92
113
  ```erb
93
- <%= cloudflare_turnstile_tag data: { theme: 'light', language: 'en' } %>
114
+ <%= cloudflare_turnstile_tag data: { theme: 'dark' } %>
115
+ ```
116
+
117
+ * To drop a configured default on a single tag (so its attribute isn't rendered at all), pass `nil` for that key:
118
+
119
+ ```erb
120
+ <%= cloudflare_turnstile_tag data: { theme: nil } %>
94
121
  ```
95
122
 
96
123
  * For all available **data-**\* options (e.g., `action`, `cdata`, `theme`, etc.), refer to the official Cloudflare client-side rendering docs:
@@ -127,6 +154,22 @@ Supports `Rails >= 5.0` with `Ruby >= 2.6.0`.
127
154
  end
128
155
  ```
129
156
 
157
+ The automatic message is a regular flash, so it survives exactly one redirect. If you **re-render the form** instead of redirecting, pass `flash: :now` to scope the message to that render, so it doesn't also appear on the next page the visitor opens:
158
+
159
+ ```ruby
160
+ def create
161
+ if valid_turnstile?(flash: :now)
162
+ # Passed: no message is set either way
163
+ redirect_to dashboard_path, notice: 'Success!'
164
+ else
165
+ # Failed: flash.now[:alert] is automatically set
166
+ render :new, status: :unprocessable_entity
167
+ end
168
+ end
169
+ ```
170
+
171
+ Passing a `model` is the other option for a re-rendered form: the failure goes to `model.errors` and no flash is set at all.
172
+
130
173
  * You may also pass additional **siteverify** parameters (e.g., `secret`, `response`, `remoteip`, `idempotency_key`) supported by Cloudflare's API:
131
174
  [Cloudflare Server-Side Validation Parameters](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/#required-parameters)
132
175
 
@@ -275,9 +318,9 @@ Cloudflare provides dummy sitekeys and secret keys for development and testing.
275
318
  | Sitekey | Description | Visibility |
276
319
  |----------------------------|---------------------------------|------------|
277
320
  | `1x00000000000000000000AA` | Always passes | visible |
278
- | `2x00000000000000000000AB` | Always blocks | visible |
321
+ | `2x00000000000000000000AB` | Always fails | visible |
279
322
  | `1x00000000000000000000BB` | Always passes | invisible |
280
- | `2x00000000000000000000BB` | Always blocks | invisible |
323
+ | `2x00000000000000000000BB` | Always fails | invisible |
281
324
  | `3x00000000000000000000FF` | Forces an interactive challenge | visible |
282
325
 
283
326
  ### Dummy Secret Keys
@@ -366,10 +409,11 @@ If you run into any issues after upgrading Rails, please [open an issue](https:/
366
409
 
367
410
  ### Setup
368
411
 
369
- Install dependencies, linters, and prepare everything in one step:
412
+ Install the Ruby dependencies, then the JavaScript dependencies used by the ESLint step:
370
413
 
371
414
  ```bash
372
415
  bin/setup
416
+ npm install
373
417
  ```
374
418
 
375
419
  ### Running the Test Suite
@@ -387,13 +431,13 @@ bundle exec appraisal rake test
387
431
 
388
432
  ### Code Linting
389
433
 
390
- Enforce code style with RuboCop (latest Ruby only):
434
+ Run RuboCop and ESLint together (autocorrecting by default, or pass `--no-fix` to only report):
391
435
 
392
436
  ```bash
393
- bundle exec rubocop
437
+ bin/lint
394
438
  ```
395
439
 
396
- > **CI Note:** We run this via [.github/workflows/lint.yml](https://github.com/vkononov/cloudflare-turnstile-rails/blob/main/.github/workflows/lint.yml) on the latest Ruby only.
440
+ > **CI Note:** We run `bin/lint --no-fix` via [.github/workflows/lint.yml](https://github.com/vkononov/cloudflare-turnstile-rails/blob/main/.github/workflows/lint.yml) on the latest Ruby only.
397
441
 
398
442
  ### Generating Rails Apps Locally
399
443
 
@@ -434,4 +478,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/vkonon
434
478
 
435
479
  ## License
436
480
 
437
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
481
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/license/MIT).
@@ -3,7 +3,7 @@ module Cloudflare
3
3
  module Rails
4
4
  class Configuration
5
5
  attr_writer :script_url
6
- attr_accessor :site_key, :secret_key, :render, :onload, :auto_populate_response_in_test_env
6
+ attr_accessor :site_key, :secret_key, :render, :onload, :default_data, :auto_populate_response_in_test_env
7
7
 
8
8
  def initialize
9
9
  @script_url = Cloudflare::SCRIPT_URL
@@ -11,6 +11,7 @@ module Cloudflare
11
11
  @secret_key = nil
12
12
  @render = nil
13
13
  @onload = nil
14
+ @default_data = {}
14
15
  @auto_populate_response_in_test_env = true
15
16
  end
16
17
 
@@ -17,10 +17,18 @@ module Cloudflare
17
17
  result
18
18
  end
19
19
 
20
- def valid_turnstile?(model: nil, **opts)
20
+ # flash: :keep carries the automatic failure message into the next request,
21
+ # for a redirect. flash: :now scopes it to the response being rendered. The
22
+ # keyword shadows the controller's own flash method, hence request.flash.
23
+ def valid_turnstile?(model: nil, flash: :keep, **opts)
21
24
  response = verify_turnstile(model: model, **opts)
22
25
  success = response.is_a?(VerificationResponse) && response.success?
23
- flash[:alert] = ErrorMessage.default if !success && model.nil?
26
+
27
+ if !success && model.nil?
28
+ store = flash == :now ? request.flash.now : request.flash
29
+ store[:alert] = ErrorMessage.default
30
+ end
31
+
24
32
  success
25
33
  end
26
34
 
@@ -7,7 +7,7 @@ module Cloudflare
7
7
  def cloudflare_turnstile_tag(site_key: nil, include_script: true, **html_options) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
8
8
  site_key ||= Rails.configuration.site_key
9
9
  html_options[:class] = Cloudflare::WIDGET_CLASS unless html_options.key?(:class)
10
- html_options[:data] ||= {}
10
+ html_options[:data] = cloudflare_turnstile_default_data.merge(html_options[:data] || {})
11
11
  html_options[:data][:sitekey] ||= site_key
12
12
 
13
13
  script_tag = nil
@@ -27,6 +27,16 @@ module Cloudflare
27
27
  widget = content_tag(:div, '', html_options)
28
28
  safe_join([script_tag, widget].compact, "\n")
29
29
  end
30
+
31
+ private
32
+
33
+ # Resolves the configured default data attributes, evaluating any
34
+ # callable values (e.g. a proc bound to I18n.locale) at render time.
35
+ def cloudflare_turnstile_default_data
36
+ (Rails.configuration.default_data || {}).transform_values do |value|
37
+ value.respond_to?(:call) ? value.call : value
38
+ end
39
+ end
30
40
  end
31
41
  end
32
42
  end
@@ -48,9 +48,7 @@ module Cloudflare
48
48
 
49
49
  module Verification
50
50
  def self.verify(response: nil, secret: nil, remoteip: nil, idempotency_key: nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
51
- if (response.nil? || response.strip.empty?) && ::Rails.env.test? && Rails.configuration.auto_populate_response_in_test_env # rubocop:disable Layout/LineLength
52
- response = 'dummy-response'
53
- end
51
+ response = 'dummy-response' if auto_populate_test_response?(response)
54
52
 
55
53
  secret ||= Rails.configuration.secret_key
56
54
  if secret.nil? || secret.strip.empty?
@@ -89,6 +87,13 @@ module Cloudflare
89
87
 
90
88
  VerificationResponse.new(json)
91
89
  end
90
+
91
+ def self.auto_populate_test_response?(response)
92
+ (response.nil? || response.strip.empty?) &&
93
+ ::Rails.env.test? &&
94
+ Rails.configuration.auto_populate_response_in_test_env
95
+ end
96
+ private_class_method :auto_populate_test_response?
92
97
  end
93
98
  end
94
99
  end
@@ -1,7 +1,7 @@
1
1
  module Cloudflare
2
2
  module Turnstile
3
3
  module Rails
4
- VERSION = '1.0.2'.freeze
4
+ VERSION = '1.2.0'.freeze
5
5
  end
6
6
  end
7
7
  end
@@ -16,6 +16,15 @@ Cloudflare::Turnstile::Rails.configure do |config|
16
16
  # config.render = 'explicit'
17
17
  # config.onload = 'onloadTurnstileCallback'
18
18
 
19
+ # Optional: Default data-* attributes applied to every `cloudflare_turnstile_tag`.
20
+ # These are merged into each widget and can be overridden per tag via the `data:` option.
21
+ # See https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#configuration-options
22
+ # Values may be a proc, evaluated at render time (e.g. to follow the current locale).
23
+ # config.default_data = {
24
+ # theme: 'auto',
25
+ # language: -> { I18n.locale }
26
+ # }
27
+
19
28
  # In the Rails Test environment, automatically fill in a dummy response if none was provided.
20
29
  # This lets you keep existing controller tests without having to add
21
30
  # params["cf-turnstile-response"] manually in every test.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudflare-turnstile-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Kononov
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  - !ruby/object:Gem::Version
84
84
  version: '0'
85
85
  requirements: []
86
- rubygems_version: 4.0.10
86
+ rubygems_version: 3.7.2
87
87
  specification_version: 4
88
88
  summary: Cloudflare Turnstile gem for Rails with built-in Turbo and Turbolinks support
89
89
  and CSP compliance