recaptcha 4.13.1 → 5.1.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.13.1'
4
+ VERSION = '5.1.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.13.1
4
+ version: 5.1.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: 2018-12-01 00:00:00.000000000 Z
11
+ date: 2019-10-01 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
- scrolling="no" name="ReCAPTCHA"
29
- style="width: 302px; height: 422px; border-style: none; border: 0;">
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,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- module Recaptcha
6
- module Verify
7
- # Your private API can be specified in the +options+ hash or preferably
8
- # using the Configuration.
9
- def verify_recaptcha(options = {})
10
- options = {model: options} unless options.is_a? Hash
11
- return true if Recaptcha::Verify.skip?(options[:env])
12
-
13
- model = options[:model]
14
- attribute = options[:attribute] || :base
15
- recaptcha_response = options[:response] || params['g-recaptcha-response'].to_s
16
-
17
- begin
18
- verified = if recaptcha_response.empty?
19
- false
20
- else
21
- recaptcha_verify_via_api_call(request, recaptcha_response, options)
22
- end
23
-
24
- if verified
25
- flash.delete(:recaptcha_error) if recaptcha_flash_supported? && !model
26
- true
27
- else
28
- recaptcha_error(
29
- model,
30
- attribute,
31
- options[:message],
32
- "recaptcha.errors.verification_failed",
33
- "reCAPTCHA verification failed, please try again."
34
- )
35
- false
36
- end
37
- rescue Timeout::Error
38
- if Recaptcha.configuration.handle_timeouts_gracefully
39
- recaptcha_error(
40
- model,
41
- attribute,
42
- options[:message],
43
- "recaptcha.errors.recaptcha_unreachable",
44
- "Oops, we failed to validate your reCAPTCHA response. Please try again."
45
- )
46
- false
47
- else
48
- raise RecaptchaError, "Recaptcha unreachable."
49
- end
50
- rescue StandardError => e
51
- raise RecaptchaError, e.message, e.backtrace
52
- end
53
- end
54
-
55
- def verify_recaptcha!(options = {})
56
- verify_recaptcha(options) || raise(VerifyError)
57
- end
58
-
59
- def self.skip?(env)
60
- env ||= ENV['RAILS_ENV'] || ENV['RACK_ENV'] || (Rails.env if defined? Rails.env)
61
- Recaptcha.configuration.skip_verify_env.include? env
62
- end
63
-
64
- private
65
-
66
- def recaptcha_verify_via_api_call(request, recaptcha_response, options)
67
- secret_key = options[:secret_key] || Recaptcha.configuration.secret_key!
68
-
69
- verify_hash = {
70
- "secret" => secret_key,
71
- "response" => recaptcha_response
72
- }
73
-
74
- unless options[:skip_remote_ip]
75
- remoteip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
76
- verify_hash["remoteip"] = remoteip.to_s
77
- end
78
-
79
- reply = JSON.parse(Recaptcha.get(verify_hash, options))
80
- reply['success'].to_s == "true" &&
81
- recaptcha_hostname_valid?(reply['hostname'], options[:hostname])
82
- end
83
-
84
- def recaptcha_hostname_valid?(hostname, validation)
85
- validation ||= Recaptcha.configuration.hostname
86
-
87
- case validation
88
- when nil, FalseClass then true
89
- when String then validation == hostname
90
- else validation.call(hostname)
91
- end
92
- end
93
-
94
- def recaptcha_error(model, attribute, message, key, default)
95
- message ||= Recaptcha.i18n(key, default)
96
- if model
97
- model.errors.add attribute, message
98
- else
99
- flash[:recaptcha_error] = message if recaptcha_flash_supported?
100
- end
101
- end
102
-
103
- def recaptcha_flash_supported?
104
- request.respond_to?(:format) && request.format == :html && respond_to?(:flash)
105
- end
106
- end
107
- end