rails_cloudflare_turnstile 0.1.2 → 0.1.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/CHANGELOG.md +8 -0
- data/README.md +3 -1
- data/app/assets/images/turnstile-logo.svg +1 -0
- data/app/assets/javascripts/mock_cloudflare_turnstile_api.js +20 -0
- data/lib/rails_cloudflare_turnstile/configuration.rb +9 -1
- data/lib/rails_cloudflare_turnstile/controller_helpers.rb +42 -38
- data/lib/rails_cloudflare_turnstile/engine.rb +9 -0
- data/lib/rails_cloudflare_turnstile/railtie.rb +3 -1
- data/lib/rails_cloudflare_turnstile/version.rb +1 -1
- data/lib/rails_cloudflare_turnstile/view_helpers.rb +35 -9
- data/lib/rails_cloudflare_turnstile.rb +8 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74e8c3cd9c2aa0d7b6efc991fe4ab26d5e4386b308a391ab38b611857df26bde
|
4
|
+
data.tar.gz: 1dae15eaf445e80b32cbd507fddee58cbc34f1c71b9ff5f5487ceb04873593a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1c3a53ed7a4dc9291aa5eb5acc1895dfd06eeaae8ee213faaee5236f4d4e5222e71f3bc8752f55864ca6637d8bde92c846c4d15eb52002c6dbabf6f28132074
|
7
|
+
data.tar.gz: e502bd59212eeec1372f927f2c70206ebe6d7ea37a2c9947ce510d723038d1a049f9c724b3f530c37010d0ac2f9ef97cb2113f1af7c7ed92f454fc91b7273a18
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -34,7 +34,6 @@ RailsCloudflareTurnstile.configure do |c|
|
|
34
34
|
c.fail_open = true
|
35
35
|
end
|
36
36
|
```
|
37
|
-
|
38
37
|
To totally disable Turnstile, you can set `c.enabled = false` and all other config values are ignored.
|
39
38
|
|
40
39
|
To use Turnstile for a view:
|
@@ -46,5 +45,8 @@ To use Turnstile for a view:
|
|
46
45
|
If the challenge fails, the exception `RailsCloudflareTurnstile::Forbidden` will be raised; you should handle this with
|
47
46
|
a `rescue_from` block.
|
48
47
|
|
48
|
+
By default, in development and test mode, a special mock view will be inserted if real credentials are not present. To
|
49
|
+
disable this, set the `mock_enable` property of the configuration to false.
|
50
|
+
|
49
51
|
## License
|
50
52
|
The gem is available as open source under the terms of the [ISC License](LICENSE.txt).
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg width="54" height="54" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M27.3146 7.26134C22.346 7.11258 17.5089 8.87182 13.7968 12.1778l1.2307-6.74308-3.1939-.58208L9.67207 16.6889 21.5124 18.8498 22.0945 15.6559l-6.0801-1.1096c2.9126-2.5542 6.6454-3.9781 10.5192-4.0126C30.4073 10.4993 34.1648 11.8565 37.1224 14.3585s4.9188 5.9826 5.5269 9.8085C43.2573 27.9929 42.4718 31.91 40.4356 35.2057c-2.0362 3.2956-5.1877 5.7509-8.8813 6.9191S23.8704 43.0965 20.3094 41.5711c-3.5609-1.5254-6.456-4.2784-8.1586-7.7582-1.7026-3.4797-2.0995-7.455-1.1185-11.2027L7.89023 21.7861c-1.02566 3.9081-.81053 8.0386.61559 11.8191C9.93194 37.3856 12.4985 40.629 15.8498 42.8861c3.3514 2.257 7.3217 3.4159 11.361 3.3162C31.2501 46.1025 35.1584 44.7491 38.3943 42.3294c3.2359-2.4196 5.6393-5.7858 6.8771-9.632C46.5092 28.8511 46.5202 24.7151 45.3029 20.8623s-3.6026-7.2317-6.8256-9.6685c-3.2229-2.43693-7.124-3.81119-11.1627-3.93246z" style="fill: rgb(243, 128, 32)"></path><path clip-rule="evenodd" d="M38.8474 21.9189 35.9285 19 24.4761 30.4524l-4.5531-4.553L17 28.8224l7.4833 7.4832 2.923-2.923L27.3949 33.3713 38.8474 21.9189z" fill-rule="evenodd" style="fill: rgb(243, 128, 32);"></path></svg>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
(function() {
|
2
|
+
function mock_cloudflare_turnstile_response() {
|
3
|
+
setTimeout(function() {
|
4
|
+
console.log("setting mock cloudflare turnstile to ✓");
|
5
|
+
for (let elem of document.getElementsByClassName("cf-turnstile")) {
|
6
|
+
elem.getElementsByTagName("p")[0].style.color = 'green';
|
7
|
+
elem.getElementsByTagName("p").innerHTML = "Mocked CAPTCHA succeeded"
|
8
|
+
if (elem.dataset.callback !== undefined) {
|
9
|
+
eval(elem.dataset.callback).call("mocked");
|
10
|
+
}
|
11
|
+
}
|
12
|
+
}, 1500);
|
13
|
+
}
|
14
|
+
|
15
|
+
if (document.readyState !== 'loading') {
|
16
|
+
mock_cloudflare_turnstile_response()
|
17
|
+
} else {
|
18
|
+
document.addEventListener('DOMContentLoaded', mock_cloudflare_turnstile_response);
|
19
|
+
}
|
20
|
+
})();
|
@@ -16,18 +16,25 @@ module RailsCloudflareTurnstile
|
|
16
16
|
# Timeout for operations with Cloudflare
|
17
17
|
attr_accessor :timeout
|
18
18
|
|
19
|
-
# size for the widget (
|
19
|
+
# size for the widget (:regular or :compact)
|
20
20
|
attr_accessor :size
|
21
21
|
|
22
|
+
# theme for the widget (:auto, :light, or :dark)
|
23
|
+
attr_accessor :theme
|
24
|
+
|
22
25
|
attr_accessor :enabled
|
23
26
|
|
27
|
+
attr_accessor :mock_enabled
|
28
|
+
|
24
29
|
def initialize
|
25
30
|
@site_key = nil
|
26
31
|
@secret_key = nil
|
27
32
|
@fail_open = true
|
28
33
|
@enabled = nil
|
34
|
+
@mock_enabled = nil
|
29
35
|
@timeout = 5.0
|
30
36
|
@size = :regular
|
37
|
+
@theme = :auto
|
31
38
|
@validation_url = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
|
32
39
|
end
|
33
40
|
|
@@ -36,6 +43,7 @@ module RailsCloudflareTurnstile
|
|
36
43
|
raise "Must set secret key" if @secret_key.nil?
|
37
44
|
@size = @size.to_sym
|
38
45
|
raise "Size must be one of ':regular' or ':compact'" unless [:regular, :compact].include? @size
|
46
|
+
raise "Theme must be one of :auto, :light, or :dark" unless [:auto, :light, :dark].include? @theme
|
39
47
|
end
|
40
48
|
|
41
49
|
def disabled?
|
@@ -5,54 +5,58 @@ require "faraday"
|
|
5
5
|
module RailsCloudflareTurnstile
|
6
6
|
module ControllerHelpers
|
7
7
|
def cloudflare_turnstile_ok?
|
8
|
-
|
8
|
+
if RailsCloudflareTurnstile.enabled?
|
9
|
+
config = RailsCloudflareTurnstile.configuration
|
9
10
|
|
10
|
-
|
11
|
+
url = URI(config.validation_url)
|
11
12
|
|
12
|
-
|
13
|
+
body = {
|
14
|
+
secret: config.secret_key,
|
15
|
+
response: params["cf-turnstile-response"],
|
16
|
+
remoteip: request.remote_ip
|
17
|
+
}
|
13
18
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
Rails.logger.error "Error response from CloudFlare Turnstile: #{e}"
|
30
|
-
if config.fail_open
|
31
|
-
return true
|
32
|
-
else
|
33
|
-
return false
|
19
|
+
begin
|
20
|
+
resp = Faraday.new(url) { |conn|
|
21
|
+
conn.options.timeout = config.timeout
|
22
|
+
conn.options.open_timeout = config.timeout
|
23
|
+
conn.use Faraday::Response::RaiseError
|
24
|
+
conn.request :json
|
25
|
+
conn.response :json
|
26
|
+
}.post(url, body)
|
27
|
+
rescue Faraday::Error => e
|
28
|
+
Rails.logger.error "Error response from CloudFlare Turnstile: #{e}"
|
29
|
+
if config.fail_open
|
30
|
+
return true
|
31
|
+
else
|
32
|
+
return false
|
33
|
+
end
|
34
34
|
end
|
35
|
-
end
|
36
35
|
|
37
|
-
|
36
|
+
json = resp.body
|
38
37
|
|
39
|
-
|
38
|
+
success = json["success"]
|
40
39
|
|
41
|
-
|
40
|
+
return true if success
|
42
41
|
|
43
|
-
|
42
|
+
error = json["error-codes"][0]
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
ActiveSupport::Notifications.instrument(
|
45
|
+
"rails_cloudflare_turnstile.failure",
|
46
|
+
message: error,
|
47
|
+
remote_ip: request.remote_ip,
|
48
|
+
user_agent: request.user_agent,
|
49
|
+
controller: params[:controller],
|
50
|
+
action: params[:action],
|
51
|
+
url: request.url
|
52
|
+
)
|
54
53
|
|
55
|
-
|
54
|
+
false
|
55
|
+
elsif RailsCloudflareTurnstile.mock_enabled?
|
56
|
+
params["cf-turnstile-response"] == "mocked"
|
57
|
+
else
|
58
|
+
true
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
62
|
private
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module RailsCloudflareTurnstile
|
2
2
|
class Railtie < ::Rails::Railtie
|
3
|
-
initializer "rails_cloudflare_turnstile" do
|
3
|
+
initializer "rails_cloudflare_turnstile" do |app|
|
4
4
|
ActiveSupport.on_load(:action_controller) do
|
5
5
|
include RailsCloudflareTurnstile::ControllerHelpers
|
6
6
|
end
|
@@ -8,6 +8,8 @@ module RailsCloudflareTurnstile
|
|
8
8
|
ActiveSupport.on_load(:action_view) do
|
9
9
|
include RailsCloudflareTurnstile::ViewHelpers
|
10
10
|
end
|
11
|
+
|
12
|
+
app.config.assets.precompile += %w[mock_cloudflare_turnstile_api.js turnstile-logo.svg]
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
@@ -2,29 +2,51 @@
|
|
2
2
|
|
3
3
|
module RailsCloudflareTurnstile
|
4
4
|
module ViewHelpers
|
5
|
-
def cloudflare_turnstile(action: "other")
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def cloudflare_turnstile(action: "other", data_callback: nil)
|
6
|
+
if RailsCloudflareTurnstile.enabled?
|
7
|
+
content_tag(:div, class: "cloudflare-turnstile") do
|
8
|
+
concat turnstile_div(action, data_callback: data_callback)
|
9
|
+
end
|
10
|
+
elsif RailsCloudflareTurnstile.mock_enabled?
|
11
|
+
content_tag(:div, class: "cloudflare-turnstile") do
|
12
|
+
concat mock_turnstile_div(action, data_callback: data_callback)
|
13
|
+
end
|
9
14
|
end
|
10
15
|
end
|
11
16
|
|
12
17
|
def cloudflare_turnstile_script_tag
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
if RailsCloudflareTurnstile.enabled?
|
19
|
+
content_tag(:script, :src => js_src, "async" => true) do
|
20
|
+
""
|
21
|
+
end
|
22
|
+
elsif RailsCloudflareTurnstile.mock_enabled?
|
23
|
+
content_tag(:script, :src => mock_js, "async" => true) do
|
24
|
+
""
|
25
|
+
end
|
16
26
|
end
|
17
27
|
end
|
18
28
|
|
19
29
|
private
|
20
30
|
|
21
|
-
def turnstile_div(action)
|
31
|
+
def turnstile_div(action, data_callback: nil)
|
22
32
|
config = RailsCloudflareTurnstile.configuration
|
23
|
-
content_tag(:div, :class => "cf-turnstile", "data-sitekey" => site_key, "data-size" => config.size, "data-action" => action) do
|
33
|
+
content_tag(:div, :class => "cf-turnstile", "data-sitekey" => site_key, "data-size" => config.size, "data-action" => action, "data-callback" => data_callback, "data-theme" => config.theme) do
|
24
34
|
""
|
25
35
|
end
|
26
36
|
end
|
27
37
|
|
38
|
+
def mock_turnstile_div(action, data_callback: nil)
|
39
|
+
content_tag(:div, :class => "cf-turnstile", :style => "width: 300px; height: 65px; border: 1px solid gray; display: flex; flex-direction: row; justify-content: center; align-items: center; margin: 10px;", "data-callback" => data_callback) do
|
40
|
+
[
|
41
|
+
tag.input(type: "hidden", name: "cf-turnstile-response", value: "mocked"),
|
42
|
+
image_tag("turnstile-logo.svg"),
|
43
|
+
content_tag(:p, style: "margin: 0") do
|
44
|
+
"CAPTCHA goes here in production"
|
45
|
+
end
|
46
|
+
].reduce(:<<)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
28
50
|
def site_key
|
29
51
|
RailsCloudflareTurnstile.configuration.site_key
|
30
52
|
end
|
@@ -32,5 +54,9 @@ module RailsCloudflareTurnstile
|
|
32
54
|
def js_src
|
33
55
|
"https://challenges.cloudflare.com/turnstile/v0/api.js"
|
34
56
|
end
|
57
|
+
|
58
|
+
def mock_js
|
59
|
+
javascript_path "mock_cloudflare_turnstile_api.js"
|
60
|
+
end
|
35
61
|
end
|
36
62
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "rails_cloudflare_turnstile/version"
|
2
|
+
require "rails_cloudflare_turnstile/engine"
|
2
3
|
require "rails_cloudflare_turnstile/configuration"
|
3
4
|
require "rails_cloudflare_turnstile/errors"
|
4
5
|
require "rails_cloudflare_turnstile/controller_helpers"
|
@@ -16,12 +17,19 @@ module RailsCloudflareTurnstile
|
|
16
17
|
if configuration.enabled.nil?
|
17
18
|
configuration.enabled = true
|
18
19
|
end
|
20
|
+
if configuration.mock_enabled.nil?
|
21
|
+
configuration.mock_enabled = Rails.env.development? || Rails.env.test?
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
def self.enabled?
|
22
26
|
configuration.enabled == true
|
23
27
|
end
|
24
28
|
|
29
|
+
def self.mock_enabled?
|
30
|
+
configuration.mock_enabled == true
|
31
|
+
end
|
32
|
+
|
25
33
|
def self.reset_configuration!
|
26
34
|
LOCK.synchronize do
|
27
35
|
@configuration = nil
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_cloudflare_turnstile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Brown
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -62,9 +62,12 @@ files:
|
|
62
62
|
- CHANGELOG.md
|
63
63
|
- README.md
|
64
64
|
- Rakefile
|
65
|
+
- app/assets/images/turnstile-logo.svg
|
66
|
+
- app/assets/javascripts/mock_cloudflare_turnstile_api.js
|
65
67
|
- lib/rails_cloudflare_turnstile.rb
|
66
68
|
- lib/rails_cloudflare_turnstile/configuration.rb
|
67
69
|
- lib/rails_cloudflare_turnstile/controller_helpers.rb
|
70
|
+
- lib/rails_cloudflare_turnstile/engine.rb
|
68
71
|
- lib/rails_cloudflare_turnstile/errors.rb
|
69
72
|
- lib/rails_cloudflare_turnstile/railtie.rb
|
70
73
|
- lib/rails_cloudflare_turnstile/version.rb
|