recaptcha-prx 4.6.6.ruby187
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +100 -0
- data/LICENSE +19 -0
- data/README.md +205 -0
- data/lib/recaptcha/client_helper.rb +127 -0
- data/lib/recaptcha/configuration.rb +58 -0
- data/lib/recaptcha/rails.rb +5 -0
- data/lib/recaptcha/railtie.rb +15 -0
- data/lib/recaptcha/verify.rb +105 -0
- data/lib/recaptcha/version.rb +3 -0
- data/lib/recaptcha.rb +76 -0
- metadata +258 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
## 4.0.0 - 2016-11-14
|
2
|
+
* public_key -> site_key and private_key -> secret_key
|
3
|
+
|
4
|
+
## 3.4.0 - 2016-11-01
|
5
|
+
* Update fallback html
|
6
|
+
|
7
|
+
## 3.2.0 - 2016-06-13
|
8
|
+
* remove SKIP_VERIFY_ENV constant, use `skip_verify_env` instance variable instead
|
9
|
+
|
10
|
+
## 3.1.0 - 2016-06-10
|
11
|
+
* better error messages
|
12
|
+
* frozen constants
|
13
|
+
|
14
|
+
## 3.0.0 - 2016-05-27
|
15
|
+
* remove all non-ssl options
|
16
|
+
|
17
|
+
## 2.3.0 - 2016-05-25
|
18
|
+
* enable ssl verification by default ... disable via `disable_ssl_verification = true`
|
19
|
+
|
20
|
+
## 2.2.0 - 2016-05-23
|
21
|
+
* Add global hostname validator config
|
22
|
+
* Clean up after with_configuration exception
|
23
|
+
|
24
|
+
## 2.1.0 - 2016-05-19
|
25
|
+
* do not query google if repactcha was not submitted
|
26
|
+
|
27
|
+
## 2.0.0 - 2016-05-17
|
28
|
+
* remove stoken support, must use custom domain verification or domain whitelist
|
29
|
+
|
30
|
+
## 1.3.0 - 2016-04-07
|
31
|
+
* do not set model error and flash
|
32
|
+
|
33
|
+
## 1.2.0 - 2016-04-01
|
34
|
+
* custom domain validation
|
35
|
+
|
36
|
+
## 1.1.0 - 2016-01-27
|
37
|
+
* support RACK_ENV
|
38
|
+
|
39
|
+
## 1.0.2 - 2015-11-30
|
40
|
+
* nice deprecations for api_version
|
41
|
+
|
42
|
+
## 1.0.1 - 2015-11-30
|
43
|
+
* no longer defines `Rails` when `recaptcha/rails` is required
|
44
|
+
|
45
|
+
## 1.0.0 - 2015-11-30
|
46
|
+
* remove api v1 support
|
47
|
+
* remove ssl_api_server_url, nonssl_api_server_url, change api_server_url to always need ssl option
|
48
|
+
* removed activesupport dependency for .to_query
|
49
|
+
* made flash and models both have descriptive errors
|
50
|
+
|
51
|
+
## 0.6.0 - 2015-11-19
|
52
|
+
* extract token module
|
53
|
+
* need to use `gem "recaptcha", require: "recaptcha/rails"` to get rails helpers installed
|
54
|
+
|
55
|
+
## 0.5.0 - 2015-11-18
|
56
|
+
* size option
|
57
|
+
* support disabling stoken
|
58
|
+
* support Rails.env
|
59
|
+
|
60
|
+
## 0.3.6 / 2012-01-07
|
61
|
+
|
62
|
+
* Many documentation changes
|
63
|
+
* Fixed deprecations in dependencies
|
64
|
+
* Protocol relative JS includes
|
65
|
+
* Fixes for options hash
|
66
|
+
* Fixes for failing tests
|
67
|
+
|
68
|
+
## 0.3.5 / 2012-05-02
|
69
|
+
|
70
|
+
* I18n for error messages
|
71
|
+
* Rails: delete flash keys if unused
|
72
|
+
|
73
|
+
## 0.3.4 / 2011-12-13
|
74
|
+
|
75
|
+
* Rails 3
|
76
|
+
* Remove jeweler
|
77
|
+
|
78
|
+
## 0.2.2 / 2009-09-14
|
79
|
+
|
80
|
+
* Add a timeout to the validator
|
81
|
+
* Give the documentation some love
|
82
|
+
|
83
|
+
## 0.2.1 / 2009-09-14
|
84
|
+
|
85
|
+
* Removed Ambethia namespace, and restructured classes a bit
|
86
|
+
* Added an example rails app in the example-rails branch
|
87
|
+
|
88
|
+
## 0.2.0 / 2009-09-12
|
89
|
+
|
90
|
+
* RecaptchaOptions AJAX API Fix
|
91
|
+
* Added 'cucumber' as a test environment to skip
|
92
|
+
* Ruby 1.9 compat fixes
|
93
|
+
* Added option :message => 'Custom error message' to verify_recaptcha
|
94
|
+
* Removed dependency on ActiveRecord constant
|
95
|
+
* Add I18n
|
96
|
+
|
97
|
+
## 0.1.0 / 2008-2-8
|
98
|
+
|
99
|
+
* 1 major enhancement
|
100
|
+
* Initial Gem Release
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2007 Jason L Perry
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
# reCAPTCHA
|
2
|
+
|
3
|
+
Author: Jason L Perry (http://ambethia.com)<br/>
|
4
|
+
Copyright: Copyright (c) 2007-2013 Jason L Perry<br/>
|
5
|
+
License: [MIT](http://creativecommons.org/licenses/MIT/)<br/>
|
6
|
+
Info: https://github.com/ambethia/recaptcha<br/>
|
7
|
+
Bugs: https://github.com/ambethia/recaptcha/issues<br/>
|
8
|
+
|
9
|
+
This plugin adds helpers for the [reCAPTCHA API](https://www.google.com/recaptcha). In your
|
10
|
+
views you can use the `recaptcha_tags` method to embed the needed javascript,
|
11
|
+
and you can validate in your controllers with `verify_recaptcha` or `verify_recaptcha!`,
|
12
|
+
which throws an error on failiure.
|
13
|
+
|
14
|
+
## Rails Installation
|
15
|
+
|
16
|
+
[obtain a reCAPTCHA API key](https://www.google.com/recaptcha/admin). Note: Use localhost or 127.0.0.1 in domain if using localhost:3000.
|
17
|
+
|
18
|
+
```Ruby
|
19
|
+
gem "recaptcha", require: "recaptcha/rails"
|
20
|
+
```
|
21
|
+
|
22
|
+
Keep keys out of the code base with environment variables.<br/>
|
23
|
+
Set in production and locally use [dotenv](https://github.com/bkeepers/dotenv), make sure to add it above recaptcha.
|
24
|
+
|
25
|
+
Otherwise see [Alternative API key setup](#alternative-api-key-setup).
|
26
|
+
|
27
|
+
```
|
28
|
+
export RECAPTCHA_SITE_KEY = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
|
29
|
+
export RECAPTCHA_SECRET_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
|
30
|
+
```
|
31
|
+
|
32
|
+
Add `recaptcha_tags` to the forms you want to protect.
|
33
|
+
|
34
|
+
```Erb
|
35
|
+
<%= form_for @foo do |f| %>
|
36
|
+
# ... other tags
|
37
|
+
<%= recaptcha_tags %>
|
38
|
+
# ... other tags
|
39
|
+
<% end %>
|
40
|
+
```
|
41
|
+
|
42
|
+
And, add `verify_recaptcha` logic to each form action that you've protected.
|
43
|
+
|
44
|
+
```Ruby
|
45
|
+
# app/controllers/users_controller.rb
|
46
|
+
@user = User.new(params[:user].permit(:name))
|
47
|
+
if verify_recaptcha(model: @user) && @user.save
|
48
|
+
redirect_to @user
|
49
|
+
else
|
50
|
+
render 'new'
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
## Sinatra / Rack / Ruby installation
|
55
|
+
|
56
|
+
See [sinatra demo](/demo/sinatra) for details.
|
57
|
+
|
58
|
+
- add `gem 'recaptcha'` to `Gemfile`
|
59
|
+
- set env variables
|
60
|
+
- `include Recaptcha::ClientHelper` where you need `recaptcha_tags`
|
61
|
+
- `include Recaptcha::Verify` where you need `verify_recaptcha`
|
62
|
+
|
63
|
+
## recaptcha_tags
|
64
|
+
|
65
|
+
Some of the options available:
|
66
|
+
|
67
|
+
| Option | Description |
|
68
|
+
|-------------|-------------|
|
69
|
+
| :noscript | Include <noscript> content (default `true`)|
|
70
|
+
| :theme | Specify the theme to be used per the API. Available options: `dark` and `light`. (default `light`)|
|
71
|
+
| :ajax | Render the dynamic AJAX captcha per the API. (default `false`)|
|
72
|
+
| :site_key | Override site API key |
|
73
|
+
| :error | Override the error code returned from the reCAPTCHA API (default `nil`)|
|
74
|
+
| :size | Specify a size (default `nil`)|
|
75
|
+
| :hl | Optional. Forces the widget to render in a specific language. Auto-detects the user's language if unspecified. (See [language codes](https://developers.google.com/recaptcha/docs/language)) |
|
76
|
+
| :id | Specify an html id attribute (default `nil`)|
|
77
|
+
| :script | If you do not need to add a script tag by helper you can set the option to false. It's necessary when you add a script tag manualy (default `true`)|
|
78
|
+
|
79
|
+
You can also override the html attributes for the sizes of the generated `textarea` and `iframe`
|
80
|
+
elements, if CSS isn't your thing. Inspect the source of `recaptcha_tags` to see these options.
|
81
|
+
|
82
|
+
## verify_recaptcha
|
83
|
+
|
84
|
+
This method returns `true` or `false` after processing the parameters from the reCAPTCHA widget. Why
|
85
|
+
isn't this a model validation? Because that violates MVC. You can use it like this, or how ever you
|
86
|
+
like. Passing in the ActiveRecord object is optional, if you do--and the captcha fails to verify--an
|
87
|
+
error will be added to the object for you to use.
|
88
|
+
|
89
|
+
Some of the options available:
|
90
|
+
|
91
|
+
| Option | Description |
|
92
|
+
|--------------|-------------|
|
93
|
+
| :model | Model to set errors.
|
94
|
+
| :attribute | Model attribute to receive errors. (default :base)
|
95
|
+
| :message | Custom error message.
|
96
|
+
| :secret_key | Override secret API key.
|
97
|
+
| :timeout | The number of seconds to wait for reCAPTCHA servers before give up. (default `3`)
|
98
|
+
| :response | Custom response parameter. (default: params['g-recaptcha-response'])
|
99
|
+
| :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`)
|
100
|
+
| :env | Current environment. The request to verify will be skipped if the environment is specified in configuration under `skip_verify_env`
|
101
|
+
|
102
|
+
## invisible_recaptcha_tags
|
103
|
+
|
104
|
+
Make sure to read [Invisible reCAPTCHA](https://developers.google.com/recaptcha/docs/invisible).
|
105
|
+
|
106
|
+
### With a single form on a page
|
107
|
+
|
108
|
+
1. The `invisible_recaptcha_tags` generates a submit button for you.
|
109
|
+
|
110
|
+
```Erb
|
111
|
+
<%= form_for @foo do |f| %>
|
112
|
+
# ... other tags
|
113
|
+
<%= invisible_recaptcha_tags text: 'Submit form' %>
|
114
|
+
<% end %>
|
115
|
+
```
|
116
|
+
|
117
|
+
Then, add `verify_recaptcha` to your controller as seen [above](#rails-installation).
|
118
|
+
|
119
|
+
### With multiple forms on a page
|
120
|
+
|
121
|
+
1. You will need a custom callback function, which is called after verification with Google's reCAPTCHA service. This callback function must submit the form. Optionally, `invisible_recaptcha_tags` currently implements a JS function called `invisibleRecaptchaSubmit` that is called when no `callback` is passed. Should you wish to override `invisibleRecaptchaSubmit`, you will need to use `invisible_recaptcha_tags script: false`, see lib/recaptcha/client_helper.rb for details.
|
122
|
+
2. The `invisible_recaptcha_tags` generates a submit button for you.
|
123
|
+
|
124
|
+
```Erb
|
125
|
+
<%= form_for @foo, html: {id: 'invisible-recaptcha-form'} do |f| %>
|
126
|
+
# ... other tags
|
127
|
+
<%= invisible_recaptcha_tags callback: 'submitInvisibleRecaptchaForm', text: 'Submit form' %>
|
128
|
+
<% end %>
|
129
|
+
```
|
130
|
+
|
131
|
+
```Javascript
|
132
|
+
// app/assets/javascripts/application.js
|
133
|
+
var submitInvisibleRecaptchaForm = function () {
|
134
|
+
document.getElementById("invisible-recaptcha-form").submit();
|
135
|
+
};
|
136
|
+
```
|
137
|
+
|
138
|
+
Finally, add `verify_recaptcha` to your controller as seen [above](#rails-installation).
|
139
|
+
|
140
|
+
|
141
|
+
## I18n support
|
142
|
+
reCAPTCHA passes two types of error explanation to a linked model. It will use the I18n gem
|
143
|
+
to translate the default error message if I18n is available. To customize the messages to your locale,
|
144
|
+
add these keys to your I18n backend:
|
145
|
+
|
146
|
+
`recaptcha.errors.verification_failed` error message displayed if the captcha words didn't match
|
147
|
+
`recaptcha.errors.recaptcha_unreachable` displayed if a timeout error occured while attempting to verify the captcha
|
148
|
+
|
149
|
+
Also you can translate API response errors to human friendly by adding translations to the locale (`config/locales/en.yml`):
|
150
|
+
|
151
|
+
```Yaml
|
152
|
+
en:
|
153
|
+
recaptcha:
|
154
|
+
errors:
|
155
|
+
verification_failed: 'Fail'
|
156
|
+
```
|
157
|
+
|
158
|
+
## Testing
|
159
|
+
|
160
|
+
By default, reCAPTCHA is skipped in "test" and "cucumber" env. To enable it during test:
|
161
|
+
|
162
|
+
```Ruby
|
163
|
+
Recaptcha.configuration.skip_verify_env.delete("test")
|
164
|
+
```
|
165
|
+
|
166
|
+
## Alternative API key setup
|
167
|
+
|
168
|
+
### Recaptcha.configure
|
169
|
+
|
170
|
+
```Ruby
|
171
|
+
# config/initializers/recaptcha.rb
|
172
|
+
Recaptcha.configure do |config|
|
173
|
+
config.site_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
|
174
|
+
config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
|
175
|
+
# Uncomment the following line if you are using a proxy server:
|
176
|
+
# config.proxy = 'http://myproxy.com.au:8080'
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
### Recaptcha.with_configuration
|
181
|
+
|
182
|
+
For temporary overwrites (not thread safe).
|
183
|
+
|
184
|
+
```Ruby
|
185
|
+
Recaptcha.with_configuration(site_key: '12345') do
|
186
|
+
# Do stuff with the overwritten site_key.
|
187
|
+
end
|
188
|
+
```
|
189
|
+
|
190
|
+
### Per call
|
191
|
+
|
192
|
+
Pass in keys as options at runtime, for code base with multiple reCAPTCHA setups:
|
193
|
+
|
194
|
+
```Ruby
|
195
|
+
recaptcha_tags site_key: '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
|
196
|
+
|
197
|
+
# and
|
198
|
+
|
199
|
+
verify_recaptcha secret_key: '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
|
200
|
+
```
|
201
|
+
|
202
|
+
## Misc
|
203
|
+
- Check out the [wiki](https://github.com/ambethia/recaptcha/wiki) and leave whatever you found valuable there.
|
204
|
+
- [Add multiple widgets to the same page](https://github.com/ambethia/recaptcha/wiki/Add-multiple-widgets-to-the-same-page)
|
205
|
+
- [Use Recaptcha with Devise](https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise)
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Recaptcha
|
2
|
+
module ClientHelper
|
3
|
+
# Your public API can be specified in the +options+ hash or preferably
|
4
|
+
# using the Configuration.
|
5
|
+
def recaptcha_tags(options = {})
|
6
|
+
if options.key?(:stoken)
|
7
|
+
raise(RecaptchaError, "Secure Token is deprecated. Please remove 'stoken' from your calls to recaptcha_tags.")
|
8
|
+
end
|
9
|
+
if options.key?(:ssl)
|
10
|
+
raise(RecaptchaError, "SSL is now always true. Please remove 'ssl' from your calls to recaptcha_tags.")
|
11
|
+
end
|
12
|
+
|
13
|
+
noscript = options.delete(:noscript)
|
14
|
+
|
15
|
+
html, tag_attributes, fallback_uri = Recaptcha::ClientHelper.recaptcha_components(options)
|
16
|
+
html << %(<div #{tag_attributes}></div>\n)
|
17
|
+
|
18
|
+
if noscript != false
|
19
|
+
html << <<-HTML
|
20
|
+
<noscript>
|
21
|
+
<div>
|
22
|
+
<div style="width: 302px; height: 422px; position: relative;">
|
23
|
+
<div style="width: 302px; height: 422px; position: absolute;">
|
24
|
+
<iframe
|
25
|
+
src="#{fallback_uri}"
|
26
|
+
frameborder="0" scrolling="no"
|
27
|
+
style="width: 302px; height:422px; border-style: none;">
|
28
|
+
title="ReCAPTCHA"
|
29
|
+
</iframe>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
<div style="width: 300px; height: 60px; border-style: none;
|
33
|
+
bottom: 12px; left: 25px; margin: 0px; padding: 0px; right: 25px;
|
34
|
+
background: #f9f9f9; border: 1px solid #c1c1c1; border-radius: 3px;">
|
35
|
+
<textarea id="g-recaptcha-response" name="g-recaptcha-response"
|
36
|
+
class="g-recaptcha-response"
|
37
|
+
style="width: 250px; height: 40px; border: 1px solid #c1c1c1;
|
38
|
+
margin: 10px 25px; padding: 0px; resize: none;" value="">
|
39
|
+
</textarea>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
</noscript>
|
43
|
+
HTML
|
44
|
+
end
|
45
|
+
|
46
|
+
html.respond_to?(:html_safe) ? html.html_safe : html
|
47
|
+
end
|
48
|
+
|
49
|
+
# Invisible reCAPTCHA implementation
|
50
|
+
def invisible_recaptcha_tags(options = {})
|
51
|
+
options = { :callback => 'invisibleRecaptchaSubmit' }.merge(options)
|
52
|
+
text = options.delete(:text)
|
53
|
+
html, tag_attributes = Recaptcha::ClientHelper.recaptcha_components(options)
|
54
|
+
html << recaptcha_default_callback if recaptcha_default_callback_required?(options)
|
55
|
+
html << %(<button type="submit" #{tag_attributes}>#{text}</button>\n)
|
56
|
+
html.respond_to?(:html_safe) ? html.html_safe : html
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.recaptcha_components(options = {})
|
60
|
+
html = ""
|
61
|
+
attributes = {}
|
62
|
+
fallback_uri = ""
|
63
|
+
|
64
|
+
# Since leftover options get passed directly through as tag
|
65
|
+
# attributes, we must unconditionally delete all our options
|
66
|
+
options = options.dup
|
67
|
+
env = options.delete(:env)
|
68
|
+
class_attribute = options.delete(:class)
|
69
|
+
site_key = options.delete(:site_key)
|
70
|
+
hl = options.delete(:hl).to_s
|
71
|
+
skip_script = (options.delete(:script) == false)
|
72
|
+
data_attributes = {}
|
73
|
+
[:badge, :theme, :type, :callback, :expired_callback, :size, :tabindex].each do |data_attribute|
|
74
|
+
value = options.delete(data_attribute)
|
75
|
+
data_attributes["data-#{data_attribute.to_s.tr('_', '-')}"] = value if value
|
76
|
+
end
|
77
|
+
|
78
|
+
unless Recaptcha::Verify.skip?(env)
|
79
|
+
site_key ||= Recaptcha.configuration.site_key!
|
80
|
+
script_url = Recaptcha.configuration.api_server_url
|
81
|
+
script_url += "?hl=#{hl}" unless hl == ""
|
82
|
+
html << %(<script src="#{script_url}" async defer></script>\n) unless skip_script
|
83
|
+
fallback_uri = %(#{script_url.chomp(".js")}/fallback?k=#{site_key})
|
84
|
+
attributes["data-sitekey"] = site_key
|
85
|
+
attributes.merge! data_attributes
|
86
|
+
end
|
87
|
+
|
88
|
+
# Append whatever that's left of options to be attributes on the tag.
|
89
|
+
attributes["class"] = "g-recaptcha #{class_attribute}"
|
90
|
+
tag_attributes = attributes.merge(options).map { |k, v| %(#{k}="#{v}") }.join(" ")
|
91
|
+
|
92
|
+
[html, tag_attributes, fallback_uri]
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def recaptcha_default_callback
|
98
|
+
<<-HTML
|
99
|
+
<script>
|
100
|
+
var invisibleRecaptchaSubmit = function () {
|
101
|
+
var closestForm = function (ele) {
|
102
|
+
var curEle = ele.parentNode;
|
103
|
+
while (curEle.nodeName !== 'FORM' && curEle.nodeName !== 'BODY'){
|
104
|
+
curEle = curEle.parentNode;
|
105
|
+
}
|
106
|
+
return curEle.nodeName === 'FORM' ? curEle : null
|
107
|
+
};
|
108
|
+
|
109
|
+
var eles = document.getElementsByClassName('g-recaptcha');
|
110
|
+
if (eles.length > 0) {
|
111
|
+
var form = closestForm(eles[0]);
|
112
|
+
if (form) {
|
113
|
+
form.submit();
|
114
|
+
}
|
115
|
+
}
|
116
|
+
};
|
117
|
+
</script>
|
118
|
+
HTML
|
119
|
+
end
|
120
|
+
|
121
|
+
def recaptcha_default_callback_required?(options)
|
122
|
+
options[:callback] == 'invisibleRecaptchaSubmit' &&
|
123
|
+
!Recaptcha::Verify.skip?(options[:env]) &&
|
124
|
+
options[:script] != false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Recaptcha
|
2
|
+
# This class enables detailed configuration of the recaptcha services.
|
3
|
+
#
|
4
|
+
# By calling
|
5
|
+
#
|
6
|
+
# Recaptcha.configuration # => instance of Recaptcha::Configuration
|
7
|
+
#
|
8
|
+
# or
|
9
|
+
# Recaptcha.configure do |config|
|
10
|
+
# config # => instance of Recaptcha::Configuration
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# you are able to perform configuration updates.
|
14
|
+
#
|
15
|
+
# Your are able to customize all attributes listed below. All values have
|
16
|
+
# sensitive default and will very likely not need to be changed.
|
17
|
+
#
|
18
|
+
# Please note that the site and secret key for the reCAPTCHA API Access
|
19
|
+
# have no useful default value. The keys may be set via the Shell enviroment
|
20
|
+
# or using this configuration. Settings within this configuration always take
|
21
|
+
# precedence.
|
22
|
+
#
|
23
|
+
# Setting the keys with this Configuration
|
24
|
+
#
|
25
|
+
# Recaptcha.configure do |config|
|
26
|
+
# config.site_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
|
27
|
+
# config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
class Configuration
|
31
|
+
attr_accessor :skip_verify_env, :secret_key, :site_key, :api_server_url, :verify_url, :proxy,
|
32
|
+
:handle_timeouts_gracefully, :hostname
|
33
|
+
|
34
|
+
def initialize #:nodoc:
|
35
|
+
@skip_verify_env = %w[test cucumber]
|
36
|
+
@handle_timeouts_gracefully = HANDLE_TIMEOUTS_GRACEFULLY
|
37
|
+
|
38
|
+
@secret_key = ENV['RECAPTCHA_SECRET_KEY']
|
39
|
+
@site_key = ENV['RECAPTCHA_SITE_KEY']
|
40
|
+
end
|
41
|
+
|
42
|
+
def secret_key!
|
43
|
+
secret_key || raise(RecaptchaError, "No secret key specified.")
|
44
|
+
end
|
45
|
+
|
46
|
+
def site_key!
|
47
|
+
site_key || raise(RecaptchaError, "No site key specified.")
|
48
|
+
end
|
49
|
+
|
50
|
+
def api_server_url
|
51
|
+
@api_server_url || CONFIG.fetch('server_url')
|
52
|
+
end
|
53
|
+
|
54
|
+
def verify_url
|
55
|
+
@verify_url || CONFIG.fetch('verify_url')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'recaptcha'
|
3
|
+
|
4
|
+
module Rails
|
5
|
+
module Recaptcha
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
initializer "setup config" do
|
8
|
+
begin
|
9
|
+
ActionView::Base.send(:include, ::Recaptcha::ClientHelper)
|
10
|
+
ActionController::Base.send(:include, ::Recaptcha::Verify)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Recaptcha
|
4
|
+
module Verify
|
5
|
+
# Your private API can be specified in the +options+ hash or preferably
|
6
|
+
# using the Configuration.
|
7
|
+
def verify_recaptcha(options = {})
|
8
|
+
options = { :model => options } unless options.is_a? Hash
|
9
|
+
return true if Recaptcha::Verify.skip?(options[:env])
|
10
|
+
|
11
|
+
model = options[:model]
|
12
|
+
attribute = options[:attribute] || :base
|
13
|
+
recaptcha_response = options[:response] || params['g-recaptcha-response'].to_s
|
14
|
+
|
15
|
+
begin
|
16
|
+
verified = if recaptcha_response.empty?
|
17
|
+
false
|
18
|
+
else
|
19
|
+
recaptcha_verify_via_api_call(request, recaptcha_response, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
if verified
|
23
|
+
flash.delete(:recaptcha_error) if recaptcha_flash_supported? && !model
|
24
|
+
true
|
25
|
+
else
|
26
|
+
recaptcha_error(
|
27
|
+
model,
|
28
|
+
attribute,
|
29
|
+
options[:message],
|
30
|
+
"recaptcha.errors.verification_failed",
|
31
|
+
"reCAPTCHA verification failed, please try again."
|
32
|
+
)
|
33
|
+
false
|
34
|
+
end
|
35
|
+
rescue Timeout::Error
|
36
|
+
if Recaptcha.configuration.handle_timeouts_gracefully
|
37
|
+
recaptcha_error(
|
38
|
+
model,
|
39
|
+
attribute,
|
40
|
+
options[:message],
|
41
|
+
"recaptcha.errors.recaptcha_unreachable",
|
42
|
+
"Oops, we failed to validate your reCAPTCHA response. Please try again."
|
43
|
+
)
|
44
|
+
false
|
45
|
+
else
|
46
|
+
raise RecaptchaError, "Recaptcha unreachable."
|
47
|
+
end
|
48
|
+
rescue StandardError => e
|
49
|
+
raise RecaptchaError, e.message, e.backtrace
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def verify_recaptcha!(options = {})
|
54
|
+
verify_recaptcha(options) || raise(VerifyError)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.skip?(env)
|
58
|
+
env ||= ENV['RACK_ENV'] || ENV['RAILS_ENV'] || (Rails.env if defined? Rails.env)
|
59
|
+
Recaptcha.configuration.skip_verify_env.include? env
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def recaptcha_verify_via_api_call(request, recaptcha_response, options)
|
65
|
+
secret_key = options[:secret_key] || Recaptcha.configuration.secret_key!
|
66
|
+
|
67
|
+
verify_hash = {
|
68
|
+
"secret" => secret_key,
|
69
|
+
"response" => recaptcha_response
|
70
|
+
}
|
71
|
+
|
72
|
+
unless options[:skip_remote_ip]
|
73
|
+
remoteip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
|
74
|
+
verify_hash["remoteip"] = remoteip.to_s
|
75
|
+
end
|
76
|
+
|
77
|
+
reply = JSON.parse(Recaptcha.get(verify_hash, options))
|
78
|
+
reply['success'].to_s == "true" &&
|
79
|
+
recaptcha_hostname_valid?(reply['hostname'], options[:hostname])
|
80
|
+
end
|
81
|
+
|
82
|
+
def recaptcha_hostname_valid?(hostname, validation)
|
83
|
+
validation ||= Recaptcha.configuration.hostname
|
84
|
+
|
85
|
+
case validation
|
86
|
+
when nil, FalseClass then true
|
87
|
+
when String then validation == hostname
|
88
|
+
else validation.call(hostname)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def recaptcha_error(model, attribute, message, key, default)
|
93
|
+
message ||= Recaptcha.i18n(key, default)
|
94
|
+
if model
|
95
|
+
model.errors.add attribute, message
|
96
|
+
else
|
97
|
+
flash[:recaptcha_error] = message if recaptcha_flash_supported?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def recaptcha_flash_supported?
|
102
|
+
request.respond_to?(:format) && request.format == :html && respond_to?(:flash)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/recaptcha.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'recaptcha/configuration'
|
2
|
+
require 'recaptcha/client_helper'
|
3
|
+
require 'recaptcha/verify'
|
4
|
+
require 'uri'
|
5
|
+
require 'net/http'
|
6
|
+
require 'rack/utils'
|
7
|
+
|
8
|
+
module Recaptcha
|
9
|
+
CONFIG = {
|
10
|
+
'server_url' => 'https://www.google.com/recaptcha/api.js',
|
11
|
+
'verify_url' => 'https://www.google.com/recaptcha/api/siteverify'
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
USE_SSL_BY_DEFAULT = false
|
15
|
+
HANDLE_TIMEOUTS_GRACEFULLY = true
|
16
|
+
DEFAULT_TIMEOUT = 3
|
17
|
+
|
18
|
+
# Gives access to the current Configuration.
|
19
|
+
def self.configuration
|
20
|
+
@configuration ||= Configuration.new
|
21
|
+
end
|
22
|
+
|
23
|
+
# Allows easy setting of multiple configuration options. See Configuration
|
24
|
+
# for all available options.
|
25
|
+
#--
|
26
|
+
# The temp assignment is only used to get a nicer rdoc. Feel free to remove
|
27
|
+
# this hack.
|
28
|
+
#++
|
29
|
+
def self.configure
|
30
|
+
config = configuration
|
31
|
+
yield(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.with_configuration(config)
|
35
|
+
original_config = {}
|
36
|
+
|
37
|
+
config.each do |key, value|
|
38
|
+
original_config[key] = configuration.send(key)
|
39
|
+
configuration.send("#{key}=", value)
|
40
|
+
end
|
41
|
+
|
42
|
+
yield if block_given?
|
43
|
+
ensure
|
44
|
+
original_config.each { |key, value| configuration.send("#{key}=", value) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.get(verify_hash, options)
|
48
|
+
http = if Recaptcha.configuration.proxy
|
49
|
+
proxy_server = URI.parse(Recaptcha.configuration.proxy)
|
50
|
+
Net::HTTP::Proxy(proxy_server.host, proxy_server.port, proxy_server.user, proxy_server.password)
|
51
|
+
else
|
52
|
+
Net::HTTP
|
53
|
+
end
|
54
|
+
query = Rack::Utils.build_query(verify_hash)
|
55
|
+
uri = URI.parse(Recaptcha.configuration.verify_url + '?' + query)
|
56
|
+
http_instance = http.new(uri.host, uri.port)
|
57
|
+
http_instance.read_timeout = http_instance.open_timeout = options[:timeout] || DEFAULT_TIMEOUT
|
58
|
+
http_instance.use_ssl = true if uri.port == 443
|
59
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
60
|
+
http_instance.request(request).body
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.i18n(key, default)
|
64
|
+
if defined?(I18n)
|
65
|
+
I18n.translate(key, :default => default)
|
66
|
+
else
|
67
|
+
default
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class RecaptchaError < StandardError
|
72
|
+
end
|
73
|
+
|
74
|
+
class VerifyError < RecaptchaError
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: recaptcha-prx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: -781170372
|
5
|
+
prerelease: 6
|
6
|
+
segments:
|
7
|
+
- 4
|
8
|
+
- 6
|
9
|
+
- 6
|
10
|
+
- ruby
|
11
|
+
- 187
|
12
|
+
version: 4.6.6.ruby187
|
13
|
+
platform: ruby
|
14
|
+
authors:
|
15
|
+
- Jason L Perry
|
16
|
+
- Andrew Kuklewicz
|
17
|
+
autorequire:
|
18
|
+
bindir: bin
|
19
|
+
cert_chain: []
|
20
|
+
|
21
|
+
date: 2018-04-02 00:00:00 Z
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 53
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 8
|
33
|
+
- 1
|
34
|
+
version: 1.8.1
|
35
|
+
prerelease: false
|
36
|
+
requirement: *id001
|
37
|
+
type: :runtime
|
38
|
+
name: json
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 19
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 1
|
49
|
+
- 0
|
50
|
+
version: 1.1.0
|
51
|
+
prerelease: false
|
52
|
+
requirement: *id002
|
53
|
+
type: :runtime
|
54
|
+
name: rack
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 7
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 4
|
65
|
+
- 0
|
66
|
+
version: 1.4.0
|
67
|
+
prerelease: false
|
68
|
+
requirement: *id003
|
69
|
+
type: :development
|
70
|
+
name: mocha
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 49
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
- 8
|
81
|
+
- 7
|
82
|
+
version: 0.8.7
|
83
|
+
prerelease: false
|
84
|
+
requirement: *id004
|
85
|
+
type: :development
|
86
|
+
name: rake
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 23
|
94
|
+
segments:
|
95
|
+
- 2
|
96
|
+
- 3
|
97
|
+
- 10
|
98
|
+
version: 2.3.10
|
99
|
+
prerelease: false
|
100
|
+
requirement: *id005
|
101
|
+
type: :development
|
102
|
+
name: activesupport
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 17
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
- 6
|
113
|
+
- 11
|
114
|
+
version: 0.6.11
|
115
|
+
prerelease: false
|
116
|
+
requirement: *id006
|
117
|
+
type: :development
|
118
|
+
name: i18n
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
hash: 29
|
126
|
+
segments:
|
127
|
+
- 5
|
128
|
+
- 11
|
129
|
+
- 3
|
130
|
+
version: 5.11.3
|
131
|
+
prerelease: false
|
132
|
+
requirement: *id007
|
133
|
+
type: :development
|
134
|
+
name: minitest
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 3
|
142
|
+
segments:
|
143
|
+
- 1
|
144
|
+
- 4
|
145
|
+
- 2
|
146
|
+
version: 1.4.2
|
147
|
+
prerelease: false
|
148
|
+
requirement: *id008
|
149
|
+
type: :development
|
150
|
+
name: minitest-hooks
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
hash: 123
|
158
|
+
segments:
|
159
|
+
- 1
|
160
|
+
- 24
|
161
|
+
- 6
|
162
|
+
version: 1.24.6
|
163
|
+
prerelease: false
|
164
|
+
requirement: *id009
|
165
|
+
type: :development
|
166
|
+
name: webmock
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
version_requirements: &id010 !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - <
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
hash: 31
|
174
|
+
segments:
|
175
|
+
- 0
|
176
|
+
- 3
|
177
|
+
- 6
|
178
|
+
version: 0.3.6
|
179
|
+
prerelease: false
|
180
|
+
requirement: *id010
|
181
|
+
type: :development
|
182
|
+
name: hashdiff
|
183
|
+
- !ruby/object:Gem::Dependency
|
184
|
+
version_requirements: &id011 !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - <
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
hash: 31
|
190
|
+
segments:
|
191
|
+
- 2
|
192
|
+
- 4
|
193
|
+
- 0
|
194
|
+
version: 2.4.0
|
195
|
+
prerelease: false
|
196
|
+
requirement: *id011
|
197
|
+
type: :development
|
198
|
+
name: addressable
|
199
|
+
description: Helpers for the reCAPTCHA API, updated by PRX to work with Ruby 1.8.7 and Rails 2.3
|
200
|
+
email:
|
201
|
+
- jasper@ambethia.com
|
202
|
+
- kookster@gmail.com
|
203
|
+
executables: []
|
204
|
+
|
205
|
+
extensions: []
|
206
|
+
|
207
|
+
extra_rdoc_files: []
|
208
|
+
|
209
|
+
files:
|
210
|
+
- CHANGELOG.md
|
211
|
+
- LICENSE
|
212
|
+
- README.md
|
213
|
+
- lib/recaptcha.rb
|
214
|
+
- lib/recaptcha/client_helper.rb
|
215
|
+
- lib/recaptcha/configuration.rb
|
216
|
+
- lib/recaptcha/rails.rb
|
217
|
+
- lib/recaptcha/railtie.rb
|
218
|
+
- lib/recaptcha/verify.rb
|
219
|
+
- lib/recaptcha/version.rb
|
220
|
+
homepage: http://github.com/ambethia/recaptcha
|
221
|
+
licenses:
|
222
|
+
- MIT
|
223
|
+
post_install_message:
|
224
|
+
rdoc_options: []
|
225
|
+
|
226
|
+
require_paths:
|
227
|
+
- lib
|
228
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
229
|
+
none: false
|
230
|
+
requirements:
|
231
|
+
- - ">="
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
hash: 57
|
234
|
+
segments:
|
235
|
+
- 1
|
236
|
+
- 8
|
237
|
+
- 7
|
238
|
+
version: 1.8.7
|
239
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
240
|
+
none: false
|
241
|
+
requirements:
|
242
|
+
- - ">"
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
hash: 25
|
245
|
+
segments:
|
246
|
+
- 1
|
247
|
+
- 3
|
248
|
+
- 1
|
249
|
+
version: 1.3.1
|
250
|
+
requirements: []
|
251
|
+
|
252
|
+
rubyforge_project:
|
253
|
+
rubygems_version: 1.8.15
|
254
|
+
signing_key:
|
255
|
+
specification_version: 3
|
256
|
+
summary: Helpers for the reCAPTCHA API, updated by PRX to work with Ruby 1.8.7 and Rails 2.3
|
257
|
+
test_files: []
|
258
|
+
|