recaptcha-prx 4.6.6.ruby187
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.
- 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
|
+
|