Class: Incline::Recaptcha
- Inherits:
-
Object
- Object
- Incline::Recaptcha
- Defined in:
- lib/incline/recaptcha.rb
Overview
A helper class for reCAPTCHA.
To use reCAPTCHA, you will need to define recaptcha_public
and recaptcha_private
in your ‘config/secrets.yml’. If you need to use a proxy server, you will need to configure the proxy settings as well.
# config/secrets.yml
default: &default
recaptcha_public: SomeBase64StringFromGoogle
recaptcha_private: AnotherBase64StringFromGoogle
recaptcha_proxy:
host: 10.10.10.10
port: 1000
user: username
password: top_secret
Defined Under Namespace
Classes: Tag
Constant Summary collapse
- VALID_THEMES =
Gets the valid themes for the reCAPTCHA field.
[ :dark, :light ]
- VALID_TYPES =
Gets the valid types for the reCAPTCHA field.
[ :audio, :image ]
- VALID_SIZES =
Gets the valid sizes for the reCAPTCHA field.
[ :compact, :normal ]
- DISABLED =
A string that will validated when reCAPTCHA is disabled.
'0.0.0.0|disabled'
Class Method Summary collapse
-
.add ⇒ Object
Generates the bare minimum code needed to include a reCAPTCHA challenge in a form.
-
.disabled? ⇒ Boolean
Determines if recaptcha is disabled either due to a test environment or because :recaptcha_public or :recaptcha_private is not defined in
secrets.yml
. -
.onload_callbacks ⇒ Object
Contains a collection of onload callbacks for explicit reCAPTCHA fields.
-
.pause_for(&block) ⇒ Object
Pauses reCAPTCHA validation for the specified block of code.
-
.paused? ⇒ Boolean
Determines if reCAPTCHA validation is currently paused.
-
.private_key ⇒ Object
Gets the private key.
-
.proxy ⇒ Object
Gets the proxy configuration (if any).
-
.public_key ⇒ Object
Gets the public key.
-
.script_block ⇒ Object
Generates a script block to load reCAPTCHA and activate any reCAPTCHA fields.
-
.verify(options = {}) ⇒ Object
Verifies the response from a reCAPTCHA challenge.
Class Method Details
.add ⇒ Object
Generates the bare minimum code needed to include a reCAPTCHA challenge in a form.
156 157 158 159 160 |
# File 'lib/incline/recaptcha.rb', line 156 def self.add unless disabled? "<div class=\"g-recaptcha\" data-sitekey=\"#{CGI::escape_html(public_key)}\"></div>\n<script src=\"https://www.google.com/recaptcha/api.js\"></script><br>".html_safe end end |
.disabled? ⇒ Boolean
Determines if recaptcha is disabled either due to a test environment or because :recaptcha_public or :recaptcha_private is not defined in secrets.yml
.
131 132 133 |
# File 'lib/incline/recaptcha.rb', line 131 def self.disabled? temp_lock || public_key.blank? || private_key.blank? || (Rails.env.test? && !enabled_for_testing?) end |
.onload_callbacks ⇒ Object
Contains a collection of onload callbacks for explicit reCAPTCHA fields.
Used by the Incline::Recaptcha::Tag helper.
275 276 277 278 |
# File 'lib/incline/recaptcha.rb', line 275 def self.onload_callbacks # FIXME: Should probably move this to the session. @onload_callbacks ||= [] end |
.pause_for(&block) ⇒ Object
Pauses reCAPTCHA validation for the specified block of code.
297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/incline/recaptcha.rb', line 297 def self.pause_for(&block) # already paused, so just call the block. return block.call if paused? # otherwise pause and then call the block. self.temp_lock = true begin return block.call ensure self.temp_lock = false end end |
.paused? ⇒ Boolean
Determines if reCAPTCHA validation is currently paused.
312 313 314 |
# File 'lib/incline/recaptcha.rb', line 312 def self.paused? temp_lock end |
.private_key ⇒ Object
Gets the private key.
143 144 145 |
# File 'lib/incline/recaptcha.rb', line 143 def self.private_key @private_key ||= Rails.application.secrets[:recaptcha_private].to_s.strip end |
.proxy ⇒ Object
Gets the proxy configuration (if any).
149 150 151 |
# File 'lib/incline/recaptcha.rb', line 149 def self.proxy @proxy ||= (Rails.application.secrets[:recaptcha_proxy] || {}).symbolize_keys end |
.public_key ⇒ Object
Gets the public key.
137 138 139 |
# File 'lib/incline/recaptcha.rb', line 137 def self.public_key @public_key ||= Rails.application.secrets[:recaptcha_public].to_s.strip end |
.script_block ⇒ Object
Generates a script block to load reCAPTCHA and activate any reCAPTCHA fields.
282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/incline/recaptcha.rb', line 282 def self.script_block if onload_callbacks.any? ret = "<script type=\"text/javascript\">\n// <![CDATA[\nfunction recaptcha_onload() { " onload_callbacks.each { |onload| ret += CGI::escape_html(onload) + '(); ' } ret += "}\n// ]]>\n</script>\n<script type=\"text/javascript\" src=\"https://www.google.com/recaptcha/api.js?onload=recaptcha_onload&render=explicit\" async defer></script>" # clear the cache. onload_callbacks.clear ret.html_safe end end |
.verify(options = {}) ⇒ Object
Verifies the response from a reCAPTCHA challenge.
Valid options:
- model
-
Sets the model that this challenge is verifying.
- attribute
-
If a model is provided, you can supply an attribute to retrieve the response data from. This attribute should return a hash with :response and :remote_ip keys. If this is provided, then the remaining options are ignored.
- response
-
If specified, defines the response from the reCAPTCHA challenge that we want to verify. If not specified, then the request parameters (if any) are searched for the “g-recaptcha-response” value.
- remote_ip
-
If specified, defines the remote IP of the user that was challenged. If not specified, then the remote IP from the request (if any) is used.
- request
-
Specifies the request to use for information. This must be provided unless :response and :remote_ip are both specified. This is the default option if an object other than a Hash is provided to #verify.
Returns true on success, or false on failure.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/incline/recaptcha.rb', line 185 def self.verify( = {}) return true if temp_lock = { request: } unless .is_a?(::Hash) model = [:model] response = if model && [:attribute] && model.respond_to?([:attribute]) model.send([:attribute]) else nil end remote_ip = nil if response.is_a?(::Hash) remote_ip = response[:remote_ip] response = response[:response] end # model must respond to the 'errors' message and the result of that must respond to 'add' if !model || !model.respond_to?('errors') || !model.send('errors').respond_to?('add') model = nil end response ||= [:response] remote_ip ||= [:remote_ip] if response.blank? || remote_ip.blank? request = [:request] raise ArgumentError, 'Either :request must be specified or both :response and :remote_ip must be specified.' unless request response = request.params['g-recaptcha-response'] remote_ip = request.respond_to?(:remote_ip) ? request.send(:remote_ip) : ENV['REMOTE_ADDR'] end if disabled? # In tests or environments where reCAPTCHA is disabled, # the response should be 'disabled' to verify successfully. return response == 'disabled' else begin if proxy.blank? http = Net::HTTP else http = Net::HTTP::Proxy(proxy.host, proxy.port, proxy.user, proxy.password) end verify_hash = { secret: private_key, remoteip: remote_ip, response: response } recaptcha = nil Timeout::timeout(5) do uri = URI.parse('https://www.google.com/recaptcha/api/siteverify') http_instance = http.new(uri.host, uri.port) if uri.port == 443 http_instance.use_ssl = true end request = Net::HTTP::Post.new(uri.request_uri) request.set_form_data(verify_hash) recaptcha = http_instance.request(request) end answer = JSON.parse(recaptcha.body) unless answer['success'].to_s.downcase == 'true' if model model.errors.add([:attribute] || :base, 'Recaptcha verification failed.') end return false end return true rescue Timeout::Error if model model.errors.add(:base, 'Recaptcha unreachable.') end end end false end |