recaptcha 4.14.0 → 5.2.1

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.
@@ -3,13 +3,33 @@
3
3
  module Recaptcha
4
4
  class Railtie < Rails::Railtie
5
5
  ActiveSupport.on_load(:action_view) do
6
- require 'recaptcha/client_helper'
7
- include Recaptcha::ClientHelper
6
+ include Recaptcha::Adapters::ViewMethods
8
7
  end
9
8
 
10
9
  ActiveSupport.on_load(:action_controller) do
11
- require 'recaptcha/verify'
12
- include Recaptcha::Verify
10
+ include Recaptcha::Adapters::ControllerMethods
11
+ end
12
+
13
+ initializer 'recaptcha' do |app|
14
+ Recaptcha::Railtie.instance_eval do
15
+ pattern = pattern_from app.config.i18n.available_locales
16
+
17
+ add("rails/locales/#{pattern}.yml")
18
+ end
19
+ end
20
+
21
+ class << self
22
+ protected
23
+
24
+ def add(pattern)
25
+ files = Dir[File.join(File.dirname(__FILE__), '../..', pattern)]
26
+ I18n.load_path.concat(files)
27
+ end
28
+
29
+ def pattern_from(args)
30
+ array = Array(args || [])
31
+ array.blank? ? '*' : "{#{array.join ','}}"
32
+ end
13
33
  end
14
34
  end
15
35
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Recaptcha
4
- VERSION = '4.14.0'
4
+ VERSION = '5.2.1'
5
5
  end
@@ -0,0 +1,5 @@
1
+ en:
2
+ recaptcha:
3
+ errors:
4
+ verification_failed: reCAPTCHA verification failed, please try again.
5
+ recaptcha_unreachable: Oops, we failed to validate your reCAPTCHA response. Please try again.
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: 4.14.0
4
+ version: 5.2.1
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: 2019-04-01 00:00:00.000000000 Z
11
+ date: 2019-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: activesupport
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: i18n
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -161,16 +147,19 @@ files:
161
147
  - LICENSE
162
148
  - README.md
163
149
  - lib/recaptcha.rb
164
- - lib/recaptcha/client_helper.rb
150
+ - lib/recaptcha/adapters/controller_methods.rb
151
+ - lib/recaptcha/adapters/view_methods.rb
165
152
  - lib/recaptcha/configuration.rb
153
+ - lib/recaptcha/helpers.rb
166
154
  - lib/recaptcha/rails.rb
167
155
  - lib/recaptcha/railtie.rb
168
- - lib/recaptcha/verify.rb
169
156
  - lib/recaptcha/version.rb
157
+ - rails/locales/en.yml
170
158
  homepage: http://github.com/ambethia/recaptcha
171
159
  licenses:
172
160
  - MIT
173
- metadata: {}
161
+ metadata:
162
+ source_code_uri: https://github.com/ambethia/recaptcha
174
163
  post_install_message:
175
164
  rdoc_options: []
176
165
  require_paths:
@@ -186,8 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
175
  - !ruby/object:Gem::Version
187
176
  version: '0'
188
177
  requirements: []
189
- rubyforge_project:
190
- rubygems_version: 2.7.6
178
+ rubygems_version: 3.0.3
191
179
  signing_key:
192
180
  specification_version: 4
193
181
  summary: Helpers for the reCAPTCHA API
@@ -1,157 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Recaptcha
4
- module ClientHelper
5
- # Your public API can be specified in the +options+ hash or preferably
6
- # using the Configuration.
7
- def recaptcha_tags(options = {})
8
- if options.key?(:stoken)
9
- raise(RecaptchaError, "Secure Token is deprecated. Please remove 'stoken' from your calls to recaptcha_tags.")
10
- end
11
- if options.key?(:ssl)
12
- raise(RecaptchaError, "SSL is now always true. Please remove 'ssl' from your calls to recaptcha_tags.")
13
- end
14
-
15
- noscript = options.delete(:noscript)
16
-
17
- html, tag_attributes, fallback_uri = Recaptcha::ClientHelper.recaptcha_components(options)
18
- html << %(<div #{tag_attributes}></div>\n)
19
-
20
- if noscript != false
21
- html << <<-HTML
22
- <noscript>
23
- <div>
24
- <div style="width: 302px; height: 422px; position: relative;">
25
- <div style="width: 302px; height: 422px; position: absolute;">
26
- <iframe
27
- src="#{fallback_uri}"
28
- name="ReCAPTCHA"
29
- style="width: 302px; height: 422px; border-style: none; border: 0; overflow: hidden;">
30
- </iframe>
31
- </div>
32
- </div>
33
- <div style="width: 300px; height: 60px; border-style: none;
34
- bottom: 12px; left: 25px; margin: 0px; padding: 0px; right: 25px;
35
- background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px;">
36
- <textarea id="g-recaptcha-response" name="g-recaptcha-response"
37
- class="g-recaptcha-response"
38
- style="width: 250px; height: 40px; border: 1px solid #c1c1c1;
39
- margin: 10px 25px; padding: 0px; resize: none;">
40
- </textarea>
41
- </div>
42
- </div>
43
- </noscript>
44
- HTML
45
- end
46
-
47
- html.respond_to?(:html_safe) ? html.html_safe : html
48
- end
49
-
50
- # Invisible reCAPTCHA implementation
51
- def invisible_recaptcha_tags(options = {})
52
- options = {callback: 'invisibleRecaptchaSubmit', ui: :button}.merge options
53
- text = options.delete(:text)
54
- html, tag_attributes = Recaptcha::ClientHelper.recaptcha_components(options)
55
- html << recaptcha_default_callback(options) if recaptcha_default_callback_required?(options)
56
- case options[:ui]
57
- when :button
58
- html << %(<button type="submit" #{tag_attributes}>#{text}</button>\n)
59
- when :invisible
60
- html << %(<div data-size="invisible" #{tag_attributes}></div>\n)
61
- when :input
62
- html << %(<input type="submit" #{tag_attributes} value="#{text}"/>\n)
63
- else
64
- raise(RecaptchaError, "ReCAPTCHA ui `#{options[:ui]}` is not valid.")
65
- end
66
- html.respond_to?(:html_safe) ? html.html_safe : html
67
- end
68
-
69
- def self.recaptcha_components(options = {})
70
- html = +''
71
- attributes = {}
72
- fallback_uri = +''
73
-
74
- # Since leftover options get passed directly through as tag
75
- # attributes, we must unconditionally delete all our options
76
- options = options.dup
77
- env = options.delete(:env)
78
- class_attribute = options.delete(:class)
79
- site_key = options.delete(:site_key)
80
- hl = options.delete(:hl)
81
- onload = options.delete(:onload)
82
- render = options.delete(:render)
83
- nonce = options.delete(:nonce)
84
- skip_script = (options.delete(:script) == false)
85
- ui = options.delete(:ui)
86
-
87
- data_attribute_keys = [:badge, :theme, :type, :callback, :expired_callback, :error_callback, :size]
88
- data_attribute_keys << :tabindex unless ui == :button
89
- data_attributes = {}
90
- data_attribute_keys.each do |data_attribute|
91
- value = options.delete(data_attribute)
92
- data_attributes["data-#{data_attribute.to_s.tr('_', '-')}"] = value if value
93
- end
94
-
95
- unless Recaptcha::Verify.skip?(env)
96
- site_key ||= Recaptcha.configuration.site_key!
97
- script_url = Recaptcha.configuration.api_server_url
98
- query_params = hash_to_query(
99
- hl: hl,
100
- onload: onload,
101
- render: render
102
- )
103
- script_url += "?#{query_params}" unless query_params.empty?
104
- nonce_attr = " nonce='#{nonce}'" if nonce
105
- html << %(<script src="#{script_url}" async defer#{nonce_attr}></script>\n) unless skip_script
106
- fallback_uri = %(#{script_url.chomp(".js")}/fallback?k=#{site_key})
107
- attributes["data-sitekey"] = site_key
108
- attributes.merge! data_attributes
109
- end
110
-
111
- # Append whatever that's left of options to be attributes on the tag.
112
- attributes["class"] = "g-recaptcha #{class_attribute}"
113
- tag_attributes = attributes.merge(options).map { |k, v| %(#{k}="#{v}") }.join(" ")
114
-
115
- [html, tag_attributes, fallback_uri]
116
- end
117
-
118
- private
119
-
120
- def recaptcha_default_callback(options = {})
121
- nonce = options[:nonce]
122
- nonce_attr = " nonce='#{nonce}'" if nonce
123
-
124
- <<-HTML
125
- <script#{nonce_attr}>
126
- var invisibleRecaptchaSubmit = function () {
127
- var closestForm = function (ele) {
128
- var curEle = ele.parentNode;
129
- while (curEle.nodeName !== 'FORM' && curEle.nodeName !== 'BODY'){
130
- curEle = curEle.parentNode;
131
- }
132
- return curEle.nodeName === 'FORM' ? curEle : null
133
- };
134
-
135
- var eles = document.getElementsByClassName('g-recaptcha');
136
- if (eles.length > 0) {
137
- var form = closestForm(eles[0]);
138
- if (form) {
139
- form.submit();
140
- }
141
- }
142
- };
143
- </script>
144
- HTML
145
- end
146
-
147
- def recaptcha_default_callback_required?(options)
148
- options[:callback] == 'invisibleRecaptchaSubmit' &&
149
- !Recaptcha::Verify.skip?(options[:env]) &&
150
- options[:script] != false
151
- end
152
-
153
- private_class_method def self.hash_to_query(hash)
154
- hash.delete_if { |_, val| val.nil? || val.empty? }.to_a.map { |pair| pair.join('=') }.join('&')
155
- end
156
- end
157
- end
@@ -1,108 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- module Recaptcha
6
- module Verify
7
- G_RESPONSE_LIMIT = 4000
8
- # Your private API can be specified in the +options+ hash or preferably
9
- # using the Configuration.
10
- def verify_recaptcha(options = {})
11
- options = {model: options} unless options.is_a? Hash
12
- return true if Recaptcha::Verify.skip?(options[:env])
13
-
14
- model = options[:model]
15
- attribute = options[:attribute] || :base
16
- recaptcha_response = options[:response] || params['g-recaptcha-response'].to_s
17
-
18
- begin
19
- verified = if recaptcha_response.empty? || recaptcha_response.length > G_RESPONSE_LIMIT
20
- false
21
- else
22
- recaptcha_verify_via_api_call(request, recaptcha_response, options)
23
- end
24
-
25
- if verified
26
- flash.delete(:recaptcha_error) if recaptcha_flash_supported? && !model
27
- true
28
- else
29
- recaptcha_error(
30
- model,
31
- attribute,
32
- options[:message],
33
- "recaptcha.errors.verification_failed",
34
- "reCAPTCHA verification failed, please try again."
35
- )
36
- false
37
- end
38
- rescue Timeout::Error
39
- if Recaptcha.configuration.handle_timeouts_gracefully
40
- recaptcha_error(
41
- model,
42
- attribute,
43
- options[:message],
44
- "recaptcha.errors.recaptcha_unreachable",
45
- "Oops, we failed to validate your reCAPTCHA response. Please try again."
46
- )
47
- false
48
- else
49
- raise RecaptchaError, "Recaptcha unreachable."
50
- end
51
- rescue StandardError => e
52
- raise RecaptchaError, e.message, e.backtrace
53
- end
54
- end
55
-
56
- def verify_recaptcha!(options = {})
57
- verify_recaptcha(options) || raise(VerifyError)
58
- end
59
-
60
- def self.skip?(env)
61
- env ||= ENV['RAILS_ENV'] || ENV['RACK_ENV'] || (Rails.env if defined? Rails.env)
62
- Recaptcha.configuration.skip_verify_env.include? env
63
- end
64
-
65
- private
66
-
67
- def recaptcha_verify_via_api_call(request, recaptcha_response, options)
68
- secret_key = options[:secret_key] || Recaptcha.configuration.secret_key!
69
-
70
- verify_hash = {
71
- "secret" => secret_key,
72
- "response" => recaptcha_response
73
- }
74
-
75
- unless options[:skip_remote_ip]
76
- remoteip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
77
- verify_hash["remoteip"] = remoteip.to_s
78
- end
79
-
80
- reply = JSON.parse(Recaptcha.get(verify_hash, options))
81
- reply['success'].to_s == "true" &&
82
- recaptcha_hostname_valid?(reply['hostname'], options[:hostname])
83
- end
84
-
85
- def recaptcha_hostname_valid?(hostname, validation)
86
- validation ||= Recaptcha.configuration.hostname
87
-
88
- case validation
89
- when nil, FalseClass then true
90
- when String then validation == hostname
91
- else validation.call(hostname)
92
- end
93
- end
94
-
95
- def recaptcha_error(model, attribute, message, key, default)
96
- message ||= Recaptcha.i18n(key, default)
97
- if model
98
- model.errors.add attribute, message
99
- else
100
- flash[:recaptcha_error] = message if recaptcha_flash_supported?
101
- end
102
- end
103
-
104
- def recaptcha_flash_supported?
105
- request.respond_to?(:format) && request.format == :html && respond_to?(:flash)
106
- end
107
- end
108
- end