rails_cloudflare_turnstile 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7ce536746c6d1d1f449d59496cfa6c8f03473cdce982577ae6972700a9508cc9
4
+ data.tar.gz: 9044b74740d86b7e7b32bb541ea8aff5c91aa316b024fc5a8b273194aea3676d
5
+ SHA512:
6
+ metadata.gz: bc15941cad051ee625472d759b848c69a26a2d0eb2e24d41f49484c9e82421df220f5780ed6978243c7e4983823a6df14a04194dce6e5dfef102a74f43af26e7
7
+ data.tar.gz: e83b60d1b28fdb0b958444f7c20b66dd4e1aef49201b62a66f01883f059229b2dbfde15a99b9b45771af45476044ddfe600117a628800eec24bfcb7b907b3e01
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # RailsCloudflareTurnstile
2
+
3
+ This is a Rails plugin adding support for [Cloudflare Turnstile](https://www.cloudflare.com/products/turnstile/)
4
+
5
+ ## Usage
6
+ How to use my plugin.
7
+
8
+ ## Installation
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'rails_cloudflare_turnstile'
13
+ ```
14
+
15
+ And then execute:
16
+ ```bash
17
+ $ bundle
18
+ ```
19
+
20
+ Or install it yourself as:
21
+ ```bash
22
+ $ gem install rails_cloudflare_turnstile
23
+ ```
24
+
25
+ Next, configure it by creating a `config/initializers/cloudflare_turnstile.rb` with contents like the following:
26
+
27
+ ```ruby
28
+ RailsCloudflareTurnstile.configure do |c|
29
+ c.site_key = "XXXXXX"
30
+ c.secret_key = "XXXXXXXX"
31
+ c.fail_open = true
32
+ end
33
+ ```
34
+
35
+ To totally disable Turnstile, you can set `c.enabled = false` and all other config values are ignored.
36
+
37
+ To use Turnstile for a view:
38
+
39
+ 1. Call `cloudflare_turnstile_script_tag` in your layout
40
+ 2. Call `cloudflare_turnstile` in your form View
41
+ 3. Call `validate_cloudflare_turnstile` as a `before_action` in your controller.
42
+
43
+ If the challenge fails, the exception `RailsCloudflareTurnstile::Forbidden` will be raised; you should handle this with
44
+ a `rescue_from` block.
45
+
46
+ ## License
47
+ The gem is available as open source under the terms of the [ISC License](LICENSE.txt).
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler/setup"
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require "rake/testtask"
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << "test"
9
+ t.pattern = "test/**/*_test.rb"
10
+ t.verbose = false
11
+ end
12
+
13
+ task default: :test
@@ -0,0 +1,45 @@
1
+ module RailsCloudflareTurnstile
2
+ class Configuration
3
+ # site key (your public key)
4
+ attr_accessor :site_key
5
+
6
+ # secret key
7
+ attr_accessor :secret_key
8
+
9
+ # if true, then a failure to contact cloudflare will allow all requests
10
+ # if false, then a failure to contact cloudflare will block all requests
11
+ # defaults to true
12
+ attr_accessor :fail_open
13
+
14
+ attr_accessor :validation_url
15
+
16
+ # Timeout for operations with Cloudflare
17
+ attr_accessor :timeout
18
+
19
+ # size for the widget ("regular" or "compact")
20
+ attr_accessor :size
21
+
22
+ attr_accessor :enabled
23
+
24
+ def initialize
25
+ @site_key = nil
26
+ @secret_key = nil
27
+ @fail_open = true
28
+ @enabled = nil
29
+ @timeout = 5.0
30
+ @size = :regular
31
+ @validation_url = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
32
+ end
33
+
34
+ def validate!
35
+ raise "Must set site key" if @site_key.nil?
36
+ raise "Must set secret key" if @secret_key.nil?
37
+ @size = @size.to_sym
38
+ raise "Size must be one of ':regular' or ':compact'" unless [:regular, :compact].include? @size
39
+ end
40
+
41
+ def disabled?
42
+ @enabled == false
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+
5
+ module RailsCloudflareTurnstile
6
+ module ControllerHelpers
7
+ def cloudflare_turnstile_ok?
8
+ return true unless RailsCloudflareTurnstile.enabled?
9
+
10
+ config = RailsCloudflareTurnstile.configuration
11
+
12
+ url = URI(config.validation_url)
13
+
14
+ body = {
15
+ secret: config.secret_key,
16
+ response: params["cf-turnstile-response"],
17
+ remoteip: request.remote_ip
18
+ }
19
+
20
+ begin
21
+ resp = Faraday.new(url) { |conn|
22
+ conn.options.timeout = config.timeout
23
+ conn.options.open_timeout = config.timeout
24
+ conn.use Faraday::Response::RaiseError
25
+ conn.request :json
26
+ conn.response :json
27
+ }.post(url, body)
28
+ rescue Faraday::Error => e
29
+ Rails.logger.error "Error response from CloudFlare Turnstile: #{e}"
30
+ if config.fail_open
31
+ return true
32
+ else
33
+ return false
34
+ end
35
+ end
36
+
37
+ json = resp.body
38
+
39
+ success = json["success"]
40
+
41
+ return true if success
42
+
43
+ error = json["error-codes"][0]
44
+
45
+ ActiveSupport::Notifications.instrument(
46
+ "rails_cloudflare_turnstile.failure",
47
+ message: error,
48
+ remote_ip: request.remote_ip,
49
+ user_agent: request.user_agent,
50
+ controller: params[:controller],
51
+ action: params[:action],
52
+ url: request.url
53
+ )
54
+
55
+ false
56
+ end
57
+
58
+ private
59
+
60
+ def validate_cloudflare_turnstile
61
+ return if cloudflare_turnstile_ok?
62
+ raise RailsCloudflareTurnstile::Forbidden
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ module RailsCloudflareTurnstile
2
+ class Error < StandardError
3
+ end
4
+
5
+ class Forbidden < Error
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module RailsCloudflareTurnstile
2
+ class Railtie < ::Rails::Railtie
3
+ initializer "rails_cloudflare_turnstile" do
4
+ ActiveSupport.on_load(:action_controller) do
5
+ include RailsCloudflareTurnstile::ControllerHelpers
6
+ end
7
+
8
+ ActiveSupport.on_load(:action_view) do
9
+ include RailsCloudflareTurnstile::ViewHelpers
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module RailsCloudflareTurnstile
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsCloudflareTurnstile
4
+ module ViewHelpers
5
+ def cloudflare_turnstile(action: "other")
6
+ return nil unless RailsCloudflareTurnstile.enabled?
7
+ content_tag(:div, class: "cloudflare-turnstile") do
8
+ concat turnstile_div(action)
9
+ end
10
+ end
11
+
12
+ def cloudflare_turnstile_script_tag
13
+ return nil unless RailsCloudflareTurnstile.enabled?
14
+ content_tag(:script, :src => js_src, "async" => true) do
15
+ ""
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def turnstile_div(action)
22
+ config = RailsCloudflareTurnstile.configuration
23
+ content_tag(:div, :class => "cf-turnstile", "data-sitekey" => site_key, "data-size" => config.size, "data-action" => action) do
24
+ ""
25
+ end
26
+ end
27
+
28
+ def site_key
29
+ RailsCloudflareTurnstile.configuration.site_key
30
+ end
31
+
32
+ def js_src
33
+ "https://challenges.cloudflare.com/turnstile/v0/api.js"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ require "rails_cloudflare_turnstile/version"
2
+ require "rails_cloudflare_turnstile/configuration"
3
+ require "rails_cloudflare_turnstile/errors"
4
+ require "rails_cloudflare_turnstile/controller_helpers"
5
+ require "rails_cloudflare_turnstile/view_helpers"
6
+ require "rails_cloudflare_turnstile/railtie"
7
+
8
+ module RailsCloudflareTurnstile
9
+ LOCK = Mutex.new
10
+
11
+ def self.configure
12
+ yield(configuration) if block_given?
13
+ unless configuration.disabled?
14
+ configuration.validate!
15
+ end
16
+ if configuration.enabled.nil?
17
+ configuration.enabled = true
18
+ end
19
+ end
20
+
21
+ def self.enabled?
22
+ configuration.enabled == true
23
+ end
24
+
25
+ def self.reset_configuration!
26
+ LOCK.synchronize do
27
+ @configuration = nil
28
+ end
29
+ end
30
+
31
+ def self.configuration
32
+ @configuration = nil unless defined?(@configuration)
33
+ @configuration || LOCK.synchronize { @configuration ||= RailsCloudflareTurnstile::Configuration.new }
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_cloudflare_turnstile
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Brown
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7.1'
33
+ - !ruby/object:Gem::Dependency
34
+ name: faraday
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '3.0'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '1.0'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '3.0'
53
+ description: |2
54
+ Rails extension for Cloudflare's Turnstile CAPTCHA alternative. This gem should work with
55
+ Rails 5.x, 6.x, and 7.x, and with Faraday 1.x and 2.x.
56
+ email:
57
+ - james@instrumentl.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - README.md
63
+ - Rakefile
64
+ - lib/rails_cloudflare_turnstile.rb
65
+ - lib/rails_cloudflare_turnstile/configuration.rb
66
+ - lib/rails_cloudflare_turnstile/controller_helpers.rb
67
+ - lib/rails_cloudflare_turnstile/errors.rb
68
+ - lib/rails_cloudflare_turnstile/railtie.rb
69
+ - lib/rails_cloudflare_turnstile/version.rb
70
+ - lib/rails_cloudflare_turnstile/view_helpers.rb
71
+ homepage: https://github.com/instrumentl/rails_cloudflare-turnstile
72
+ licenses:
73
+ - ISC
74
+ metadata:
75
+ homepage_uri: https://github.com/instrumentl/rails_cloudflare-turnstile
76
+ source_code_uri: https://github.com/instrumentl/rails_cloudflare-turnstile
77
+ changelog_uri: https://github.com/dotenv-org/cloudflare_turnstile
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 2.7.0
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubygems_version: 3.4.2
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Rails extension for Cloudflare's Turnstile CAPTCHA alternative
97
+ test_files: []