recaptcha 4.14.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,13 +3,11 @@
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
13
11
  end
14
12
  end
15
13
  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.0.0'
5
5
  end
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.0.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: 2019-04-01 00:00:00.000000000 Z
11
+ date: 2019-06-05 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,18 @@ 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
170
157
  homepage: http://github.com/ambethia/recaptcha
171
158
  licenses:
172
159
  - MIT
173
- metadata: {}
160
+ metadata:
161
+ source_code_uri: https://github.com/ambethia/recaptcha
174
162
  post_install_message:
175
163
  rdoc_options: []
176
164
  require_paths:
@@ -186,8 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
174
  - !ruby/object:Gem::Version
187
175
  version: '0'
188
176
  requirements: []
189
- rubyforge_project:
190
- rubygems_version: 2.7.6
177
+ rubygems_version: 3.0.3
191
178
  signing_key:
192
179
  specification_version: 4
193
180
  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