recaptcha 5.5.0 → 5.12.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba681f9321310ca16bb41dc622bf7051c30df10ec000582f9dd8d29310e21136
4
- data.tar.gz: 8d9a3a4a7adb2ea830f17ace469e6b475d4d5c633c6988cd04dd56a7fd70e414
3
+ metadata.gz: 4052ca42cf536d84329b553a058de58f2c3579e0ac2ad1e08ba42fed8ce974b4
4
+ data.tar.gz: 90c873c15d0772690ca3da6cf2588669a05c159e4fbaa1d6bdf5d809ad05dfd0
5
5
  SHA512:
6
- metadata.gz: efba5551493debe23617c41db429c224f51a4d0253274cf6fe28c5e384d78f4bd374ba3ad3132c2009cb2df9813266ac3a90eabd9a019aa7d48ee3999f2451e3
7
- data.tar.gz: 1dfd4f2281c8f6902b1c70ca0d272d0d2f671d9062669f147cfb38416ee771e7348ff131c8fd957c1e8674b7d83ad3f3c79f6c306a7779638b4481000534f695
6
+ metadata.gz: 403d9de96d890bb3f75cfb83c5907f01944d8e88233248ec199fe014e04f7f1386c13cd867c9020a232cd5501faada986f6d3413d3a2369e5d38d9c56a0704b9
7
+ data.tar.gz: ce0d965054455acff094e60ccad808fbf836992666f9bd1233684b172e766440ba922a0f8d030803575b3a538945e3273d0ae237ce2527f9e0983b7b76671328
data/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  ## Next
2
2
 
3
+ ## 5.12.3
4
+ * Remove score fallback for enterprise
5
+ * Update enterprise tests to v1 assessment schema
6
+
7
+ ## 5.12.2
8
+ * Fix minimum score for enterprise
9
+
10
+ ## 5.12.1
11
+ * Fix Japanese locale
12
+
13
+ ## 5.12.0
14
+ * Added Japanese locale
15
+
16
+ ## 5.11.0
17
+ * Added Dutch locale
18
+
19
+ ## 5.10.1
20
+ * Fix enterprise_verify_url #415
21
+
22
+ ## 5.10.0
23
+ * Drop ruby 2.4 2.5 2.6
24
+ * Add maxiumm score support for hcaptcha
25
+
26
+ ## 5.9.0
27
+ * Gracefully handle invalid params
28
+
29
+ ## 5.8.1
30
+ * Allow configuring response limit
31
+
32
+ ## 5.8.0
33
+ * Add support for the enterprise API
34
+
35
+ ## 5.7.0
36
+ * french locale
37
+ * drop ruby 2.3
38
+
39
+ ## 5.6.0
40
+ * Allow multiple invisible recaptchas on a single page by setting custom selector
41
+
42
+ ## 5.5.0
43
+ * add `recaptcha_reply` controller method for better debugging/inspection
44
+
45
+ ## 5.4.1
46
+ * fix v2 vs 'data' postfix
47
+
48
+ ## 5.4.0
49
+ * added 'data' postfix to g-recaptcha-response attribute name to avoid collisions
50
+
3
51
  ## 5.3.0
4
52
  * turbolinks support
5
53
 
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  # reCAPTCHA
2
3
  [![Gem Version](https://badge.fury.io/rb/recaptcha.svg)](https://badge.fury.io/rb/recaptcha)
3
4
 
@@ -12,6 +13,23 @@ views you can use the `recaptcha_tags` method to embed the needed javascript, an
12
13
  in your controllers with `verify_recaptcha` or `verify_recaptcha!`, which raises an error on
13
14
  failure.
14
15
 
16
+
17
+ # Table of Contents
18
+ 1. [Obtaining a key](#obtaining-a-key)
19
+ 2. [Rails Installation](#rails-installation)
20
+ 3. [Sinatra / Rack / Ruby Installation](#sinatra--rack--ruby-installation)
21
+ 4. [reCAPTCHA V2 API & Usage](#recaptcha-v2-api-and-usage)
22
+ - [`recaptcha_tags`](#recaptcha_tags)
23
+ - [`verify_recaptcha`](#verify_recaptcha)
24
+ - [`invisible_recaptcha_tags`](#invisible_recaptcha_tags)
25
+ 5. [reCAPTCHA V3 API & Usage](#recaptcha-v3-api-and-usage)
26
+ - [`recaptcha_v3`](#recaptcha_v3)
27
+ - [`verify_recaptcha` (use with v3)](#verify_recaptcha-use-with-v3)
28
+ - [`recaptcha_reply`](#recaptcha_reply)
29
+ 6. [I18n Support](#i18n-support)
30
+ 7. [Testing](#testing)
31
+ 8. [Alternative API Key Setup](#alternative-api-key-setup)
32
+
15
33
  ## Obtaining a key
16
34
 
17
35
  Go to the [reCAPTCHA admin console](https://www.google.com/recaptcha/admin) to obtain a reCAPTCHA API key.
@@ -32,6 +50,8 @@ Note: Enter `localhost` or `127.0.0.1` as the domain if using in development wit
32
50
 
33
51
  ## Rails Installation
34
52
 
53
+ **If you are having issues with Rails 7, Turbo, and Stimulus, make sure to check [this Wiki page](https://github.com/ambethia/recaptcha/wiki/Recaptcha-with-Turbo-and-Stimulus)!**
54
+
35
55
  ```ruby
36
56
  gem "recaptcha"
37
57
  ```
@@ -50,6 +70,14 @@ export RECAPTCHA_SITE_KEY = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
50
70
  export RECAPTCHA_SECRET_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
51
71
  ```
52
72
 
73
+ If you have an Enterprise API key:
74
+
75
+ ```shell
76
+ export RECAPTCHA_ENTERPRISE = 'true'
77
+ export RECAPTCHA_ENTERPRISE_API_KEY = 'AIzvFyE3TU-g4K_Kozr9F1smEzZSGBVOfLKyupA'
78
+ export RECAPTCHA_ENTERPRISE_PROJECT_ID = 'my-project'
79
+ ```
80
+
53
81
  Add `recaptcha_tags` to the forms you want to protect:
54
82
 
55
83
  ```erb
@@ -71,6 +99,7 @@ else
71
99
  render 'new'
72
100
  end
73
101
  ```
102
+ Please note that this setup uses [`reCAPTCHA_v2`](#recaptcha-v2-api-and-usage). For a `recaptcha_v3` use, please refer to [`reCAPTCHA_v3 setup`](#examples).
74
103
 
75
104
  ## Sinatra / Rack / Ruby installation
76
105
 
@@ -119,7 +148,7 @@ The following options are available:
119
148
  Any unrecognized options will be added as attributes on the generated tag.
120
149
 
121
150
  You can also override the html attributes for the sizes of the generated `textarea` and `iframe`
122
- elements, if CSS isn't your thing. Inspect the [source of `recaptcha_tags`](https://github.com/ambethia/recaptcha/blob/master/lib/recaptcha/client_helper.rb)
151
+ elements, if CSS isn't your thing. Inspect the [source of `recaptcha_tags`](https://github.com/ambethia/recaptcha/blob/master/lib/recaptcha/helpers.rb)
123
152
  to see these options.
124
153
 
125
154
  Note that you cannot submit/verify the same response token more than once or you will get a
@@ -140,16 +169,18 @@ you like.
140
169
 
141
170
  Some of the options available:
142
171
 
143
- | Option | Description |
144
- |----------------|-------------|
145
- | `:model` | Model to set errors.
146
- | `:attribute` | Model attribute to receive errors. (default: `:base`)
147
- | `:message` | Custom error message.
148
- | `:secret_key` | Override the secret API key from the configuration.
149
- | `:timeout` | The number of seconds to wait for reCAPTCHA servers before give up. (default: `3`)
150
- | `:response` | Custom response parameter. (default: `params['g-recaptcha-response-data']`)
151
- | `:hostname` | Expected hostname or a callable that validates the hostname, see [domain validation](https://developers.google.com/recaptcha/docs/domain_validation) and [hostname](https://developers.google.com/recaptcha/docs/verify#api-response) docs. (default: `nil`, but can be changed by setting `config.hostname`)
152
- | `:env` | Current environment. The request to verify will be skipped if the environment is specified in configuration under `skip_verify_env`
172
+ | Option | Description |
173
+ |---------------------------|-------------|
174
+ | `:model` | Model to set errors.
175
+ | `:attribute` | Model attribute to receive errors. (default: `:base`)
176
+ | `:message` | Custom error message.
177
+ | `:secret_key` | Override the secret API key from the configuration.
178
+ | `:enterprise_api_key` | Override the Enterprise API key from the configuration.
179
+ | `:enterprise_project_id ` | Override the Enterprise project ID from the configuration.
180
+ | `:timeout` | The number of seconds to wait for reCAPTCHA servers before give up. (default: `3`)
181
+ | `:response` | Custom response parameter. (default: `params['g-recaptcha-response-data']`)
182
+ | `:hostname` | Expected hostname or a callable that validates the hostname, see [domain validation](https://developers.google.com/recaptcha/docs/domain_validation) and [hostname](https://developers.google.com/recaptcha/docs/verify#api-response) docs. (default: `nil`, but can be changed by setting `config.hostname`)
183
+ | `:env` | Current environment. The request to verify will be skipped if the environment is specified in configuration under `skip_verify_env`
153
184
 
154
185
 
155
186
  ### `invisible_recaptcha_tags`
@@ -278,7 +309,7 @@ threshold:
278
309
  <% if @show_checkbox_recaptcha %>
279
310
  <%= recaptcha_tags %>
280
311
  <% else %>
281
- <%= recaptcha_v3(action: 'login') %>
312
+ <%= recaptcha_v3(action: 'login', site_key: ENV['RECAPTCHA_SITE_KEY_V3']) %>
282
313
  <% end %>
283
314
 
284
315
  ```
@@ -286,7 +317,7 @@ threshold:
286
317
  ```ruby
287
318
  # app/controllers/sessions_controller.rb
288
319
  def create
289
- success = verify_recaptcha(action: 'login', minimum_score: 0.5)
320
+ success = verify_recaptcha(action: 'login', minimum_score: 0.5, secret_key: ENV['RECAPTCHA_SECRET_KEY_V3'])
290
321
  checkbox_success = verify_recaptcha unless success
291
322
  if success || checkbox_success
292
323
  # Perform action
@@ -357,17 +388,19 @@ then you can either:
357
388
  2. write and specify a custom `callback` function. You may also want to pass `element: false` if you
358
389
  don't have a use for the hidden input element.
359
390
 
360
- Note that you cannot submit/verify the same response token more than once or you will get a
361
- `timeout-or-duplicate` error code. If you need reset the captcha and generate a new response token,
362
- then you need to call `grecaptcha.execute(…)` again. This helper provides a JavaScript method (for
363
- each action) named `executeRecaptchaFor{action}` to make this easier. That is the same method that
364
- is invoked immediately. It simply calls `grecaptcha.execute` again and then calls the `callback`
365
- function with the response token.
391
+ Note that you cannot submit/verify the same response token more than once or you
392
+ will get a `timeout-or-duplicate` error code. If you need reset the captcha and
393
+ generate a new response token, then you need to call `grecaptcha.execute(…)` or
394
+ `grecaptcha.enterprise.execute(…)` again. This helper provides a JavaScript
395
+ method (for each action) named `executeRecaptchaFor{action}` to make this
396
+ easier. That is the same method that is invoked immediately. It simply calls
397
+ `grecaptcha.execute` or `grecaptcha.enterprise.execute` again and then calls the
398
+ `callback` function with the response token.
366
399
 
367
400
  You will also get a `timeout-or-duplicate` error if too much time has passed between getting the
368
401
  response token and verifying it. This can easily happen with large forms that take the user a couple
369
402
  minutes to complete. Unlike v2, where you can use the `expired-callback` to be notified when the
370
- response expries, v3 appears to provide no such callback. See also
403
+ response expires, v3 appears to provide no such callback. See also
371
404
  [1](https://github.com/google/recaptcha/issues/281) and
372
405
  [2](https://stackoverflow.com/questions/54437745/recaptcha-v3-how-to-deal-with-expired-token-after-idle).
373
406
 
@@ -427,7 +460,7 @@ According to https://developers.google.com/recaptcha/docs/v3#placement,
427
460
 
428
461
  > Note: You can execute reCAPTCHA as many times as you'd like with different actions on the same page.
429
462
 
430
- You will need to verify each action individually with separate call to `verify_recaptcha`.
463
+ You will need to verify each action individually with a separate call to `verify_recaptcha`.
431
464
 
432
465
  ```ruby
433
466
  result_a = verify_recaptcha(action: 'a')
@@ -487,14 +520,20 @@ Recaptcha.configuration.skip_verify_env.delete("test")
487
520
  Recaptcha.configure do |config|
488
521
  config.site_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
489
522
  config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
523
+
490
524
  # Uncomment the following line if you are using a proxy server:
491
525
  # config.proxy = 'http://myproxy.com.au:8080'
526
+
527
+ # Uncomment the following lines if you are using the Enterprise API:
528
+ # config.enterprise = true
529
+ # config.enterprise_api_key = 'AIzvFyE3TU-g4K_Kozr9F1smEzZSGBVOfLKyupA'
530
+ # config.enterprise_project_id = 'my-project'
492
531
  end
493
532
  ```
494
533
 
495
534
  ### Recaptcha.with_configuration
496
535
 
497
- For temporary overwrites (not thread safe).
536
+ For temporary overwrites (not thread-safe).
498
537
 
499
538
  ```ruby
500
539
  Recaptcha.with_configuration(site_key: '12345') do
@@ -514,6 +553,38 @@ recaptcha_tags site_key: '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
514
553
  verify_recaptcha secret_key: '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
515
554
  ```
516
555
 
556
+
557
+ ## hCaptcha support
558
+
559
+ [hCaptcha](https://hcaptcha.com) is an alternative service providing reCAPTCHA API.
560
+
561
+ To use hCaptcha:
562
+ 1. Set a site and a secret key as usual
563
+ 2. Set two options in `verify_url` and `api_service_url` pointing to hCaptcha API endpoints.
564
+ 3. Disable a response limit check by setting a `response_limit` to the large enough value (reCAPTCHA is limited by 4000 characters).
565
+ 4. It is not required to change a parameter name as [official docs suggest](https://docs.hcaptcha.com/switch) because API handles standard `g-recaptcha` for compatibility.
566
+
567
+ ```ruby
568
+ # config/initializers/recaptcha.rb
569
+ Recaptcha.configure do |config|
570
+ config.site_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
571
+ config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
572
+ config.verify_url = 'https://hcaptcha.com/siteverify'
573
+ config.api_server_url = 'https://hcaptcha.com/1/api.js'
574
+ config.response_limit = 100000
575
+ end
576
+ ```
577
+
578
+ hCaptcha uses a scoring system (higher number more likely to be a bot) which is inverse of the reCaptcha scoring system (lower number more likely to be a bot). As such, a `maximum_score` attribute is provided for use with hCaptcha.
579
+
580
+ ```ruby
581
+ result = verify_recaptcha(maximum_score: 0.7)
582
+ ```
583
+
584
+ | Option | Description |
585
+ |------------------|-------------|
586
+ | `:maximum_score` | Provide a threshold to meet or fall below. Threshold should be a float between 0 and 1 which will be tested as `score <= maximum_score`. (Default: `nil`) |
587
+
517
588
  ## Misc
518
589
  - Check out the [wiki](https://github.com/ambethia/recaptcha/wiki) and leave whatever you found valuable there.
519
590
  - [Add multiple widgets to the same page](https://github.com/ambethia/recaptcha/wiki/Add-multiple-widgets-to-the-same-page)
@@ -83,10 +83,12 @@ module Recaptcha
83
83
  # @return [String] A response token if one was passed in the params; otherwise, `''`
84
84
  def recaptcha_response_token(action = nil)
85
85
  response_param = params['g-recaptcha-response-data'] || params['g-recaptcha-response']
86
- if response_param&.respond_to?(:to_h) # Includes ActionController::Parameters
87
- response_param[action].to_s
86
+ response_param = response_param[action] if action && response_param.respond_to?(:key?)
87
+
88
+ if response_param.is_a?(String)
89
+ response_param
88
90
  else
89
- response_param.to_s
91
+ ''
90
92
  end
91
93
  end
92
94
  end
@@ -31,22 +31,32 @@ module Recaptcha
31
31
  #
32
32
  class Configuration
33
33
  DEFAULTS = {
34
- 'server_url' => 'https://www.recaptcha.net/recaptcha/api.js',
35
- 'verify_url' => 'https://www.recaptcha.net/recaptcha/api/siteverify'
34
+ 'free_server_url' => 'https://www.recaptcha.net/recaptcha/api.js',
35
+ 'enterprise_server_url' => 'https://www.recaptcha.net/recaptcha/enterprise.js',
36
+ 'free_verify_url' => 'https://www.recaptcha.net/recaptcha/api/siteverify',
37
+ 'enterprise_verify_url' => 'https://recaptchaenterprise.googleapis.com/v1/projects'
36
38
  }.freeze
37
39
 
38
- attr_accessor :default_env, :skip_verify_env, :secret_key, :site_key, :proxy, :handle_timeouts_gracefully, :hostname
40
+ attr_accessor :default_env, :skip_verify_env, :proxy, :secret_key, :site_key, :handle_timeouts_gracefully,
41
+ :hostname, :enterprise, :enterprise_api_key, :enterprise_project_id, :response_limit
39
42
  attr_writer :api_server_url, :verify_url
40
43
 
41
- def initialize #:nodoc:
44
+ def initialize # :nodoc:
42
45
  @default_env = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || (Rails.env if defined? Rails.env)
43
46
  @skip_verify_env = %w[test cucumber]
44
47
  @handle_timeouts_gracefully = true
45
48
 
46
49
  @secret_key = ENV['RECAPTCHA_SECRET_KEY']
47
50
  @site_key = ENV['RECAPTCHA_SITE_KEY']
51
+
52
+ @enterprise = ENV['RECAPTCHA_ENTERPRISE'] == 'true'
53
+ @enterprise_api_key = ENV['RECAPTCHA_ENTERPRISE_API_KEY']
54
+ @enterprise_project_id = ENV['RECAPTCHA_ENTERPRISE_PROJECT_ID']
55
+
48
56
  @verify_url = nil
49
57
  @api_server_url = nil
58
+
59
+ @response_limit = 4000
50
60
  end
51
61
 
52
62
  def secret_key!
@@ -57,12 +67,20 @@ module Recaptcha
57
67
  site_key || raise(RecaptchaError, "No site key specified.")
58
68
  end
59
69
 
70
+ def enterprise_api_key!
71
+ enterprise_api_key || raise(RecaptchaError, "No Enterprise API key specified.")
72
+ end
73
+
74
+ def enterprise_project_id!
75
+ enterprise_project_id || raise(RecaptchaError, "No Enterprise project ID specified.")
76
+ end
77
+
60
78
  def api_server_url
61
- @api_server_url || DEFAULTS.fetch('server_url')
79
+ @api_server_url || (enterprise ? DEFAULTS.fetch('enterprise_server_url') : DEFAULTS.fetch('free_server_url'))
62
80
  end
63
81
 
64
82
  def verify_url
65
- @verify_url || DEFAULTS.fetch('verify_url')
83
+ @verify_url || (enterprise ? DEFAULTS.fetch('enterprise_verify_url') : DEFAULTS.fetch('free_verify_url'))
66
84
  end
67
85
  end
68
86
  end
@@ -10,7 +10,7 @@ module Recaptcha
10
10
  def self.recaptcha_v3(options = {})
11
11
  site_key = options[:site_key] ||= Recaptcha.configuration.site_key!
12
12
  action = options.delete(:action) || raise(Recaptcha::RecaptchaError, 'action is required')
13
- id = options.delete(:id) || "g-recaptcha-response-data-" + dasherize_action(action)
13
+ id = options.delete(:id) || "g-recaptcha-response-data-#{dasherize_action(action)}"
14
14
  name = options.delete(:name) || "g-recaptcha-response-data[#{action}]"
15
15
  turbolinks = options.delete(:turbolinks)
16
16
  options[:render] = site_key
@@ -174,7 +174,8 @@ module Recaptcha
174
174
 
175
175
  # v3
176
176
 
177
- # Renders a script that calls `grecaptcha.execute` for the given `site_key` and `action` and
177
+ # Renders a script that calls `grecaptcha.execute` or
178
+ # `grecaptcha.enterprise.execute` for the given `site_key` and `action` and
178
179
  # calls the `callback` with the resulting response token.
179
180
  private_class_method def self.recaptcha_v3_inline_script(site_key, action, callback, id, options = {})
180
181
  nonce = options[:nonce]
@@ -185,8 +186,8 @@ module Recaptcha
185
186
  // Define function so that we can call it again later if we need to reset it
186
187
  // This executes reCAPTCHA and then calls our callback.
187
188
  function #{recaptcha_v3_execute_function_name(action)}() {
188
- grecaptcha.ready(function() {
189
- grecaptcha.execute('#{site_key}', {action: '#{action}'}).then(function(token) {
189
+ #{recaptcha_ready_method_name}(function() {
190
+ #{recaptcha_execute_method_name}('#{site_key}', {action: '#{action}'}).then(function(token) {
190
191
  #{callback}('#{id}', token)
191
192
  });
192
193
  });
@@ -199,8 +200,8 @@ module Recaptcha
199
200
  // Returns a Promise that resolves with the response token.
200
201
  async function #{recaptcha_v3_async_execute_function_name(action)}() {
201
202
  return new Promise((resolve, reject) => {
202
- grecaptcha.ready(async function() {
203
- resolve(await grecaptcha.execute('#{site_key}', {action: '#{action}'}))
203
+ #{recaptcha_ready_method_name}(async function() {
204
+ resolve(await #{recaptcha_execute_method_name}('#{site_key}', {action: '#{action}'}))
204
205
  });
205
206
  })
206
207
  };
@@ -217,8 +218,8 @@ module Recaptcha
217
218
  <<-HTML
218
219
  <script#{nonce_attr}>
219
220
  function #{recaptcha_v3_execute_function_name(action)}() {
220
- grecaptcha.ready(function() {
221
- grecaptcha.execute('#{site_key}', {action: '#{action}'}).then(function(token) {
221
+ #{recaptcha_ready_method_name}(function() {
222
+ #{recaptcha_execute_method_name}('#{site_key}', {action: '#{action}'}).then(function(token) {
222
223
  #{callback}('#{id}', token)
223
224
  });
224
225
  });
@@ -251,8 +252,9 @@ module Recaptcha
251
252
  recaptcha_v3_inline_script?(options)
252
253
  end
253
254
 
254
- # Returns the name of the JavaScript function that actually executes the reCAPTCHA code (calls
255
- # grecaptcha.execute). You can call it again later to reset it.
255
+ # Returns the name of the JavaScript function that actually executes the
256
+ # reCAPTCHA code (calls `grecaptcha.execute` or
257
+ # `grecaptcha.enterprise.execute`). You can call it again later to reset it.
256
258
  def self.recaptcha_v3_execute_function_name(action)
257
259
  "executeRecaptchaFor#{sanitize_action_for_js(action)}"
258
260
  end
@@ -271,6 +273,7 @@ module Recaptcha
271
273
  private_class_method def self.default_callback(options = {})
272
274
  nonce = options[:nonce]
273
275
  nonce_attr = " nonce='#{nonce}'" if nonce
276
+ selector_attr = options[:id] ? "##{options[:id]}" : ".g-recaptcha"
274
277
 
275
278
  <<-HTML
276
279
  <script#{nonce_attr}>
@@ -283,9 +286,9 @@ module Recaptcha
283
286
  return curEle.nodeName === 'FORM' ? curEle : null
284
287
  };
285
288
 
286
- var eles = document.getElementsByClassName('g-recaptcha');
287
- if (eles.length > 0) {
288
- var form = closestForm(eles[0]);
289
+ var el = document.querySelector("#{selector_attr}")
290
+ if (!!el) {
291
+ var form = closestForm(el);
289
292
  if (form) {
290
293
  form.submit();
291
294
  }
@@ -295,6 +298,14 @@ module Recaptcha
295
298
  HTML
296
299
  end
297
300
 
301
+ def self.recaptcha_execute_method_name
302
+ Recaptcha.configuration.enterprise ? "grecaptcha.enterprise.execute" : "grecaptcha.execute"
303
+ end
304
+
305
+ def self.recaptcha_ready_method_name
306
+ Recaptcha.configuration.enterprise ? "grecaptcha.enterprise.ready" : "grecaptcha.ready"
307
+ end
308
+
298
309
  private_class_method def self.default_callback_required?(options)
299
310
  options[:callback] == 'invisibleRecaptchaSubmit' &&
300
311
  !Recaptcha.skip_env?(options[:env]) &&
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Recaptcha
4
- VERSION = '5.5.0'
4
+ VERSION = '5.12.3'
5
5
  end
data/lib/recaptcha.rb CHANGED
@@ -14,7 +14,6 @@ end
14
14
 
15
15
  module Recaptcha
16
16
  DEFAULT_TIMEOUT = 3
17
- RESPONSE_LIMIT = 4000
18
17
 
19
18
  class RecaptchaError < StandardError
20
19
  end
@@ -56,24 +55,60 @@ module Recaptcha
56
55
  end
57
56
 
58
57
  def self.invalid_response?(resp)
59
- resp.empty? || resp.length > RESPONSE_LIMIT
58
+ resp.empty? || resp.length > configuration.response_limit
60
59
  end
61
60
 
62
61
  def self.verify_via_api_call(response, options)
62
+ if Recaptcha.configuration.enterprise
63
+ verify_via_api_call_enterprise(response, options)
64
+ else
65
+ verify_via_api_call_free(response, options)
66
+ end
67
+ end
68
+
69
+ def self.verify_via_api_call_enterprise(response, options)
70
+ site_key = options.fetch(:site_key) { configuration.site_key! }
71
+ api_key = options.fetch(:enterprise_api_key) { configuration.enterprise_api_key! }
72
+ project_id = options.fetch(:enterprise_project_id) { configuration.enterprise_project_id! }
73
+
74
+ query_params = { 'key' => api_key }
75
+ body = { 'event' => { 'token' => response, 'siteKey' => site_key } }
76
+ body['event']['expectedAction'] = options[:action] if options.key?(:action)
77
+ body['event']['userIpAddress'] = options[:remote_ip] if options.key?(:remote_ip)
78
+
79
+ reply = api_verification_enterprise(query_params, body, project_id, timeout: options[:timeout])
80
+ score = reply.dig('riskAnalysis', 'score')
81
+ token_properties = reply['tokenProperties']
82
+ success = !token_properties.nil? &&
83
+ token_properties['valid'].to_s == 'true' &&
84
+ hostname_valid?(token_properties['hostname'], options[:hostname]) &&
85
+ action_valid?(token_properties['action'], options[:action]) &&
86
+ score_above_threshold?(score, options[:minimum_score]) &&
87
+ score_below_threshold?(score, options[:maximum_score])
88
+
89
+ if options[:with_reply] == true
90
+ [success, reply]
91
+ else
92
+ success
93
+ end
94
+ end
95
+
96
+ def self.verify_via_api_call_free(response, options)
63
97
  secret_key = options.fetch(:secret_key) { configuration.secret_key! }
64
98
  verify_hash = { 'secret' => secret_key, 'response' => response }
65
99
  verify_hash['remoteip'] = options[:remote_ip] if options.key?(:remote_ip)
66
100
 
67
- reply = api_verification(verify_hash, timeout: options[:timeout])
101
+ reply = api_verification_free(verify_hash, timeout: options[:timeout])
68
102
  success = reply['success'].to_s == 'true' &&
69
103
  hostname_valid?(reply['hostname'], options[:hostname]) &&
70
104
  action_valid?(reply['action'], options[:action]) &&
71
- score_above_threshold?(reply['score'], options[:minimum_score])
105
+ score_above_threshold?(reply['score'], options[:minimum_score]) &&
106
+ score_below_threshold?(reply['score'], options[:maximum_score])
72
107
 
73
108
  if options[:with_reply] == true
74
- return success, reply
109
+ [success, reply]
75
110
  else
76
- return success
111
+ success
77
112
  end
78
113
  end
79
114
 
@@ -94,18 +129,15 @@ module Recaptcha
94
129
  end
95
130
  end
96
131
 
97
- # Returns true iff score is greater or equal to (>=) minimum_score, or if no minimum_score was specified
98
132
  def self.score_above_threshold?(score, minimum_score)
99
- return true if minimum_score.nil?
100
- return false if score.nil?
133
+ !minimum_score || (score && score >= minimum_score)
134
+ end
101
135
 
102
- case minimum_score
103
- when nil, FalseClass then true
104
- else score >= minimum_score
105
- end
136
+ def self.score_below_threshold?(score, maximum_score)
137
+ !maximum_score || (score && score <= maximum_score)
106
138
  end
107
139
 
108
- def self.api_verification(verify_hash, timeout: nil)
140
+ def self.http_client_for(uri:, timeout: nil)
109
141
  timeout ||= DEFAULT_TIMEOUT
110
142
  http = if configuration.proxy
111
143
  proxy_server = URI.parse(configuration.proxy)
@@ -113,12 +145,28 @@ module Recaptcha
113
145
  else
114
146
  Net::HTTP
115
147
  end
148
+ instance = http.new(uri.host, uri.port)
149
+ instance.read_timeout = instance.open_timeout = timeout
150
+ instance.use_ssl = true if uri.port == 443
151
+
152
+ instance
153
+ end
154
+
155
+ def self.api_verification_free(verify_hash, timeout: nil)
116
156
  query = URI.encode_www_form(verify_hash)
117
- uri = URI.parse(configuration.verify_url + '?' + query)
118
- http_instance = http.new(uri.host, uri.port)
119
- http_instance.read_timeout = http_instance.open_timeout = timeout
120
- http_instance.use_ssl = true if uri.port == 443
157
+ uri = URI.parse("#{configuration.verify_url}?#{query}")
158
+ http_instance = http_client_for(uri: uri, timeout: timeout)
121
159
  request = Net::HTTP::Get.new(uri.request_uri)
122
160
  JSON.parse(http_instance.request(request).body)
123
161
  end
162
+
163
+ def self.api_verification_enterprise(query_params, body, project_id, timeout: nil)
164
+ query = URI.encode_www_form(query_params)
165
+ uri = URI.parse("#{configuration.verify_url}/#{project_id}/assessments?#{query}")
166
+ http_instance = http_client_for(uri: uri, timeout: timeout)
167
+ request = Net::HTTP::Post.new(uri.request_uri)
168
+ request['Content-Type'] = 'application/json; charset=utf-8'
169
+ request.body = JSON.generate(body)
170
+ JSON.parse(http_instance.request(request).body)
171
+ end
124
172
  end
@@ -0,0 +1,5 @@
1
+ fr:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: La vérification reCAPTCHA a échoué, veuillez essayer à nouveau.
5
+ recaptcha_unreachable: Oops, nous n'avons pas pu valider votre réponse reCAPTCHA. Veuillez essayer à nouveau.
@@ -0,0 +1,5 @@
1
+ ja:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: reCAPTCHA認証に失敗しました。もう一度お試しください。
5
+ recaptcha_unreachable: reCAPTCHAのレスポンスを検証できませんでした。もう一度お試しください。
@@ -0,0 +1,5 @@
1
+ nl:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: reCAPTCHA-verificatie mislukt, probeer het opnieuw.
5
+ recaptcha_unreachable: Oeps, we hebben uw reCAPTCHA-antwoord niet kunnen valideren. Probeer het opnieuw.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recaptcha
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.0
4
+ version: 5.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason L Perry
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-31 00:00:00.000000000 Z
11
+ date: 2022-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -155,12 +155,15 @@ files:
155
155
  - lib/recaptcha/railtie.rb
156
156
  - lib/recaptcha/version.rb
157
157
  - rails/locales/en.yml
158
+ - rails/locales/fr.yml
159
+ - rails/locales/ja.yml
160
+ - rails/locales/nl.yml
158
161
  homepage: http://github.com/ambethia/recaptcha
159
162
  licenses:
160
163
  - MIT
161
164
  metadata:
162
165
  source_code_uri: https://github.com/ambethia/recaptcha
163
- post_install_message:
166
+ post_install_message:
164
167
  rdoc_options: []
165
168
  require_paths:
166
169
  - lib
@@ -168,15 +171,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
171
  requirements:
169
172
  - - ">="
170
173
  - !ruby/object:Gem::Version
171
- version: 2.3.0
174
+ version: 2.7.0
172
175
  required_rubygems_version: !ruby/object:Gem::Requirement
173
176
  requirements:
174
177
  - - ">="
175
178
  - !ruby/object:Gem::Version
176
179
  version: '0'
177
180
  requirements: []
178
- rubygems_version: 3.0.3
179
- signing_key:
181
+ rubygems_version: 3.3.3
182
+ signing_key:
180
183
  specification_version: 4
181
184
  summary: Helpers for the reCAPTCHA API
182
185
  test_files: []