recaptcha 5.12.0 → 5.17.0

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: 4696b1987122715318c6ea1ce3ce1930dfe1cf9aad40913e74617f746db4176b
4
- data.tar.gz: ab251d09e9ad5f9596dc8a8a0d70d9f108dbfbafaaff92fbfe72758877f84354
3
+ metadata.gz: 52997b101110f7111f307af5bc5a66ce28d71cc74af339a267d55f8fe4bdeb1d
4
+ data.tar.gz: 5b62b2bf9740563b8f4e8edc9e3fdd90303daa4e8ea205cdb94e39a842dba770
5
5
  SHA512:
6
- metadata.gz: 764ffc3bad21f61f1b6d87212af60fcfa2533fe643de904a127f4ae47227aec45965a9d118429ea262e638e9021b62387716e8e96c3748ba71cb21cf96a7edc0
7
- data.tar.gz: 5a61522e047c0a2fe8da6a6facdd4228dbd322904144f15646bf5a8ea7adbff51fbf6ce7b880a406a01192fc3adf9128a875611307b352a19f2501d72ff309a9
6
+ metadata.gz: 6fe87d18b768bcdd4bf50f6a8ba5248856bcf54d7dd5afb5c8f8f9da4003902f7078782c8f75c685874f4d1427deb1348c48d6fe001bd78aa733af0acf24060e
7
+ data.tar.gz: a0190cbff7d1e7f0d8b312ad2d6fc9e0a88336db8f8d2dea8ac9a7d678fd35faac9ec3ca7ba029f22b5b1d48614797caef9b56443e10837af1a2d5106fe7fccb
data/CHANGELOG.md CHANGED
@@ -1,8 +1,42 @@
1
1
  ## Next
2
+ * Add key setup to v3 example in README
3
+ * Remove unnecessary id from textarea - This was unused and may cause accessability concerns if there is more than one recaptcha on the page due to multiple elements with the same id
4
+ * Update to latest version of rubocop
5
+ * Drop support for Ruby 2.7; add Ruby 3.3
6
+ * Add i18n: de, es, it, pt, pt-BR
2
7
 
3
- * Added Dutch locale
8
+ ## 5.16.0
9
+ * Allow usage of `options[:turbo]` as well as `options[:turbolinks]` for `recaptcha_v3`
10
+
11
+ ## 5.15.0
12
+ * Add 3.2 to the list of Ruby CI versions
13
+ * Add ability to submit verify_recaptcha via POST with JSON Body with `options[:json] = true`
14
+
15
+ ## 5.14.0
16
+ * drop json dependency
17
+
18
+ ## 5.13.1
19
+ * Permit actions as symbol
20
+
21
+ ## 5.13.0
22
+ * Added option to ignore_no_element.
23
+
24
+ ## 5.12.3
25
+ * Remove score fallback for enterprise
26
+ * Update enterprise tests to v1 assessment schema
27
+
28
+ ## 5.12.2
29
+ * Fix minimum score for enterprise
30
+
31
+ ## 5.12.1
32
+ * Fix Japanese locale
33
+
34
+ ## 5.12.0
4
35
  * Added Japanese locale
5
36
 
37
+ ## 5.11.0
38
+ * Added Dutch locale
39
+
6
40
  ## 5.10.1
7
41
  * Fix enterprise_verify_url #415
8
42
 
data/README.md CHANGED
@@ -78,6 +78,10 @@ export RECAPTCHA_ENTERPRISE_API_KEY = 'AIzvFyE3TU-g4K_Kozr9F1smEzZSGBVOfLKyup
78
78
  export RECAPTCHA_ENTERPRISE_PROJECT_ID = 'my-project'
79
79
  ```
80
80
 
81
+ _note:_ you'll still have to provide `RECAPTCHA_SITE_KEY`, which will hold the value of your enterprise recaptcha key id. You will not need to provide a `RECAPTCHA_SECRET_KEY`, however.
82
+
83
+ `RECAPTCHA_ENTERPRISE_API_KEY` is the enterprise key of your Google Cloud Project, which you can generate here: https://console.cloud.google.com/apis/credentials.
84
+
81
85
  Add `recaptcha_tags` to the forms you want to protect:
82
86
 
83
87
  ```erb
@@ -181,6 +185,7 @@ Some of the options available:
181
185
  | `:response` | Custom response parameter. (default: `params['g-recaptcha-response-data']`)
182
186
  | `: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
187
  | `:env` | Current environment. The request to verify will be skipped if the environment is specified in configuration under `skip_verify_env`
188
+ | `:json` | Boolean; defaults to false; if true, will submit the verification request by POST with the request data in JSON
184
189
 
185
190
 
186
191
  ### `invisible_recaptcha_tags`
@@ -304,6 +309,14 @@ With v3, you can let all users log in without any intervention at all if their s
304
309
  threshold, and only show a v2 checkbox recaptcha challenge (fall back to v2) if it is below the
305
310
  threshold:
306
311
 
312
+ This example sets v2 keys through environment variables. For more information on how to set up keys, please refer to the [documentation here](#alternative-api-key-setup).
313
+
314
+ ```bash
315
+ # .env
316
+ RECAPTCHA_SITE_KEY=6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy
317
+ RECAPTCHA_SECRET_KEY=6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx
318
+ ```
319
+
307
320
  ```erb
308
321
 
309
322
  <% if @show_checkbox_recaptcha %>
@@ -418,7 +431,7 @@ but only accepts the following options:
418
431
  | Option | Description |
419
432
  |---------------------|-------------|
420
433
  | `:site_key` | Override site API key |
421
- | `:action` | The name of the [reCAPTCHA action](https://developers.google.com/recaptcha/docs/v3#actions). Actions may only contain alphanumeric characters and slashes, and must not be user-specific. |
434
+ | `:action` | The name of the [reCAPTCHA action](https://developers.google.com/recaptcha/docs/v3#actions). Actions are not case-sensitive and may only contain alphanumeric characters, slashes, and underscores, and must not be user-specific. |
422
435
  | `:nonce` | Optional. Sets nonce attribute for script. Can be generated via `SecureRandom.base64(32)`. (default: `nil`) |
423
436
  | `:callback` | Name of callback function to call with the token. When `element` is `:input`, this defaults to a function named `setInputWithRecaptchaResponseTokenFor#{sanitize_action(action)}` that sets the value of the hidden input to the token. |
424
437
  | `:id` | Specify a unique `id` attribute for the `<input>` element if using `element: :input`. (default: `"g-recaptcha-response-data-"` + `action`) |
@@ -426,7 +439,9 @@ but only accepts the following options:
426
439
  | `:script` | Same as setting both `:inline_script` and `:external_script`. (default: `true`). |
427
440
  | `:inline_script` | If `true`, adds an inline script tag that calls `grecaptcha.execute` for the given `site_key` and `action` and calls the `callback` with the resulting response token. Pass `false` if you want to handle calling `grecaptcha.execute` yourself. (default: `true`) |
428
441
  | `:element` | The element to render, if any (default: `:input`)<br/>`:input`: Renders a hidden `<input type="hidden">` tag. The value of this will be set to the response token by the default `setInputWithRecaptchaResponseTokenFor{action}` callback.<br/>`false`: Doesn't render any tag. You'll have to add a custom callback that does something with the token. |
429
- | `:turbolinks` | If `true`, calls the js function which executes reCAPTCHA after all the dependencies have been loaded. This cannot be used with the js param `:onload`. This makes reCAPTCHAv3 usable with turbolinks. |
442
+ | `:turbo` | If `true`, calls the js function which executes reCAPTCHA after all the dependencies have been loaded. This cannot be used with the js param `:onload`. This makes reCAPTCHAv3 usable with turbo. |
443
+ | `:turbolinks` | Alias of `:turbo`. Will be deprecated soon. |
444
+ | `:ignore_no_element` | If `true`, adds null element checker for forms that can be removed from the page by javascript like modals with forms. (default: true) |
430
445
 
431
446
  [JavaScript resource (api.js) parameters](https://developers.google.com/recaptcha/docs/invisible#js_param):
432
447
 
@@ -12,10 +12,11 @@ module Recaptcha
12
12
  action = options.delete(:action) || raise(Recaptcha::RecaptchaError, 'action is required')
13
13
  id = options.delete(:id) || "g-recaptcha-response-data-#{dasherize_action(action)}"
14
14
  name = options.delete(:name) || "g-recaptcha-response-data[#{action}]"
15
- turbolinks = options.delete(:turbolinks)
15
+ turbo = options.delete(:turbo) || options.delete(:turbolinks)
16
16
  options[:render] = site_key
17
17
  options[:script_async] ||= false
18
18
  options[:script_defer] ||= false
19
+ options[:ignore_no_element] = options.key?(:ignore_no_element) ? options[:ignore_no_element] : true
19
20
  element = options.delete(:element)
20
21
  element = element == false ? false : :input
21
22
  if element == :input
@@ -23,11 +24,11 @@ module Recaptcha
23
24
  end
24
25
  options[:class] = "g-recaptcha-response #{options[:class]}"
25
26
 
26
- if turbolinks
27
+ if turbo
27
28
  options[:onload] = recaptcha_v3_execute_function_name(action)
28
29
  end
29
30
  html, tag_attributes = components(options)
30
- if turbolinks
31
+ if turbo
31
32
  html << recaptcha_v3_onload_script(site_key, action, callback, id, options)
32
33
  elsif recaptcha_v3_inline_script?(options)
33
34
  html << recaptcha_v3_inline_script(site_key, action, callback, id, options)
@@ -73,7 +74,7 @@ module Recaptcha
73
74
  <div style="width: 300px; height: 60px; border-style: none;
74
75
  bottom: 12px; left: 25px; margin: 0px; padding: 0px; right: 25px;
75
76
  background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px;">
76
- <textarea id="g-recaptcha-response" name="g-recaptcha-response"
77
+ <textarea name="g-recaptcha-response"
77
78
  class="g-recaptcha-response"
78
79
  style="width: 250px; height: 40px; border: 1px solid #c1c1c1;
79
80
  margin: 10px 25px; padding: 0px; resize: none;">
@@ -138,6 +139,7 @@ module Recaptcha
138
139
  nonce = options.delete(:nonce)
139
140
  skip_script = (options.delete(:script) == false) || (options.delete(:external_script) == false)
140
141
  ui = options.delete(:ui)
142
+ options.delete(:ignore_no_element)
141
143
 
142
144
  data_attribute_keys = [:badge, :theme, :type, :callback, :expired_callback, :error_callback, :size]
143
145
  data_attribute_keys << :tabindex unless ui == :button
@@ -206,7 +208,7 @@ module Recaptcha
206
208
  })
207
209
  };
208
210
 
209
- #{recaptcha_v3_define_default_callback(callback) if recaptcha_v3_define_default_callback?(callback, action, options)}
211
+ #{recaptcha_v3_define_default_callback(callback, options) if recaptcha_v3_define_default_callback?(callback, action, options)}
210
212
  </script>
211
213
  HTML
212
214
  end
@@ -224,7 +226,7 @@ module Recaptcha
224
226
  });
225
227
  });
226
228
  };
227
- #{recaptcha_v3_define_default_callback(callback) if recaptcha_v3_define_default_callback?(callback, action, options)}
229
+ #{recaptcha_v3_define_default_callback(callback, options) if recaptcha_v3_define_default_callback?(callback, action, options)}
228
230
  </script>
229
231
  HTML
230
232
  end
@@ -235,12 +237,12 @@ module Recaptcha
235
237
  options[:inline_script] != false
236
238
  end
237
239
 
238
- private_class_method def self.recaptcha_v3_define_default_callback(callback)
240
+ private_class_method def self.recaptcha_v3_define_default_callback(callback, options)
239
241
  <<-HTML
240
- var #{callback} = function(id, token) {
241
- var element = document.getElementById(id);
242
- element.value = token;
243
- }
242
+ var #{callback} = function(id, token) {
243
+ var element = document.getElementById(id);
244
+ #{element_check_condition(options)} element.value = token;
245
+ }
244
246
  HTML
245
247
  end
246
248
 
@@ -328,5 +330,9 @@ module Recaptcha
328
330
  private_class_method def self.hash_to_query(hash)
329
331
  hash.delete_if { |_, val| val.nil? || val.empty? }.to_a.map { |pair| pair.join('=') }.join('&')
330
332
  end
333
+
334
+ private_class_method def self.element_check_condition(options)
335
+ options[:ignore_no_element] ? "if (element !== null)" : ""
336
+ end
331
337
  end
332
338
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Recaptcha
4
- VERSION = '5.12.0'
4
+ VERSION = '5.17.0'
5
5
  end
data/lib/recaptcha.rb CHANGED
@@ -77,13 +77,14 @@ module Recaptcha
77
77
  body['event']['userIpAddress'] = options[:remote_ip] if options.key?(:remote_ip)
78
78
 
79
79
  reply = api_verification_enterprise(query_params, body, project_id, timeout: options[:timeout])
80
+ score = reply.dig('riskAnalysis', 'score')
80
81
  token_properties = reply['tokenProperties']
81
82
  success = !token_properties.nil? &&
82
83
  token_properties['valid'].to_s == 'true' &&
83
84
  hostname_valid?(token_properties['hostname'], options[:hostname]) &&
84
85
  action_valid?(token_properties['action'], options[:action]) &&
85
- score_above_threshold?(reply['score'], options[:minimum_score]) &&
86
- score_below_threshold?(reply['score'], options[:maximum_score])
86
+ score_above_threshold?(score, options[:minimum_score]) &&
87
+ score_below_threshold?(score, options[:maximum_score])
87
88
 
88
89
  if options[:with_reply] == true
89
90
  [success, reply]
@@ -97,7 +98,7 @@ module Recaptcha
97
98
  verify_hash = { 'secret' => secret_key, 'response' => response }
98
99
  verify_hash['remoteip'] = options[:remote_ip] if options.key?(:remote_ip)
99
100
 
100
- reply = api_verification_free(verify_hash, timeout: options[:timeout])
101
+ reply = api_verification_free(verify_hash, timeout: options[:timeout], json: options[:json])
101
102
  success = reply['success'].to_s == 'true' &&
102
103
  hostname_valid?(reply['hostname'], options[:hostname]) &&
103
104
  action_valid?(reply['action'], options[:action]) &&
@@ -124,7 +125,7 @@ module Recaptcha
124
125
  def self.action_valid?(action, expected_action)
125
126
  case expected_action
126
127
  when nil, FalseClass then true
127
- else action == expected_action
128
+ else action == expected_action.to_s
128
129
  end
129
130
  end
130
131
 
@@ -151,11 +152,18 @@ module Recaptcha
151
152
  instance
152
153
  end
153
154
 
154
- def self.api_verification_free(verify_hash, timeout: nil)
155
- query = URI.encode_www_form(verify_hash)
156
- uri = URI.parse("#{configuration.verify_url}?#{query}")
155
+ def self.api_verification_free(verify_hash, timeout: nil, json: false)
156
+ if json
157
+ uri = URI.parse(configuration.verify_url)
158
+ request = Net::HTTP::Post.new(uri.request_uri)
159
+ request['Content-Type'] = 'application/json; charset=utf-8'
160
+ request.body = JSON.generate(verify_hash)
161
+ else
162
+ query = URI.encode_www_form(verify_hash)
163
+ uri = URI.parse("#{configuration.verify_url}?#{query}")
164
+ request = Net::HTTP::Get.new(uri.request_uri)
165
+ end
157
166
  http_instance = http_client_for(uri: uri, timeout: timeout)
158
- request = Net::HTTP::Get.new(uri.request_uri)
159
167
  JSON.parse(http_instance.request(request).body)
160
168
  end
161
169
 
@@ -0,0 +1,5 @@
1
+ de:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: Die reCAPTCHA-Überprüfung ist fehlgeschlagen, bitte versuchen Sie es erneut.
5
+ recaptcha_unreachable: Oops, wir konnten Ihre reCAPTCHA-Antwort nicht validieren. Bitte versuchen Sie es erneut.
@@ -0,0 +1,5 @@
1
+ es:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: La verificación de reCAPTCHA falló, por favor intente de nuevo.
5
+ recaptcha_unreachable: Ups, no pudimos validar su respuesta de reCAPTCHA. Por favor intente de nuevo.
@@ -0,0 +1,5 @@
1
+ it:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: La verifica reCAPTCHA non è riuscita, si prega di riprovare.
5
+ recaptcha_unreachable: Ops, non siamo riusciti a convalidare la tua risposta reCAPTCHA. Per favore riprova.
data/rails/locales/ja.yml CHANGED
@@ -1,4 +1,4 @@
1
- en:
1
+ ja:
2
2
  recaptcha:
3
3
  errors:
4
4
  verification_failed: reCAPTCHA認証に失敗しました。もう一度お試しください。
@@ -0,0 +1,5 @@
1
+ pt-BR:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: A verificação do reCAPTCHA falhou, por favor, tente novamente.
5
+ recaptcha_unreachable: Oops, não conseguimos validar sua resposta do reCAPTCHA. Por favor, tente novamente.
@@ -0,0 +1,5 @@
1
+ pt:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: A verificação do reCAPTCHA falhou, por favor, tente novamente.
5
+ recaptcha_unreachable: Oops, não conseguimos validar sua resposta do reCAPTCHA. Por favor, tente novamente.
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recaptcha
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.12.0
4
+ version: 5.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason L Perry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-28 00:00:00.000000000 Z
11
+ date: 2024-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: json
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: mocha
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -154,10 +140,15 @@ files:
154
140
  - lib/recaptcha/rails.rb
155
141
  - lib/recaptcha/railtie.rb
156
142
  - lib/recaptcha/version.rb
143
+ - rails/locales/de.yml
157
144
  - rails/locales/en.yml
145
+ - rails/locales/es.yml
158
146
  - rails/locales/fr.yml
147
+ - rails/locales/it.yml
159
148
  - rails/locales/ja.yml
160
149
  - rails/locales/nl.yml
150
+ - rails/locales/pt-BR.yml
151
+ - rails/locales/pt.yml
161
152
  homepage: http://github.com/ambethia/recaptcha
162
153
  licenses:
163
154
  - MIT
@@ -171,14 +162,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
171
162
  requirements:
172
163
  - - ">="
173
164
  - !ruby/object:Gem::Version
174
- version: 2.7.0
165
+ version: 3.0.0
175
166
  required_rubygems_version: !ruby/object:Gem::Requirement
176
167
  requirements:
177
168
  - - ">="
178
169
  - !ruby/object:Gem::Version
179
170
  version: '0'
180
171
  requirements: []
181
- rubygems_version: 3.3.3
172
+ rubygems_version: 3.4.10
182
173
  signing_key:
183
174
  specification_version: 4
184
175
  summary: Helpers for the reCAPTCHA API