recaptcha 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15a8d9b4ffc50fb479df2f03065310e3b85be5f4
4
- data.tar.gz: 1d2412b3ce72619d131388e77e9b82a4b1e9de46
3
+ metadata.gz: 19150c1891f5ef4fda5c568d941c8035ef19c0aa
4
+ data.tar.gz: ffac23399306ce2b5c6c5199389cc755abfe2833
5
5
  SHA512:
6
- metadata.gz: f1a53822196216dc231d60369edcce9719e724e4e66a35b57e35b7b57ca8104b2d5211a07231616fad499c13420daa3eb584b5337e87dd47631d40e61d801721
7
- data.tar.gz: e3fef919669e86e48de71216c3def51609e1d525d1fe7cebc5ada112f5f9613d96783625c0d675cddfeafce97d7783006665371db42be17f027248945784ebc6
6
+ metadata.gz: 0734d303c81f727913edef8c3f637b2fbf4d2f4612f170656bf1899b9a2be45fdd06401e63bd8eb9a98dac8eb57f9ffbc139a2d2d17a09f93ed0986cd349d452
7
+ data.tar.gz: cd08fa57ef7c4b3afdc03f8311ab7f4299d0c056686289a7bdff87dd87b6aa6fb5979a7313d0437c3b49ce9730c92000451f429aafe521fc66b5103f5989b8a5
@@ -1,4 +1,19 @@
1
- == 0.3.6 / 2012-01-07
1
+ ## NEXT
2
+ * remove api v1 support
3
+ * remove ssl_api_server_url, nonssl_api_server_url, change api_server_url to always need ssl option
4
+ * removed activesupport dependency for .to_query
5
+ * made flash and models both have descriptive errors
6
+
7
+ ## 0.6.0
8
+ * extract token module
9
+ * need to use `gem "recaptcha", require: "recaptcha/rails"` to get rails helpers installed
10
+
11
+ ## 0.5.0
12
+ * size option
13
+ * support disabling stoken
14
+ * support Rails.env
15
+
16
+ ## 0.3.6 / 2012-01-07
2
17
 
3
18
  * Many documentation changes
4
19
  * Fixed deprecations in dependencies
@@ -6,27 +21,27 @@
6
21
  * Fixes for options hash
7
22
  * Fixes for failing tests
8
23
 
9
- == 0.3.5 / 2012-05-02
24
+ ## 0.3.5 / 2012-05-02
10
25
 
11
26
  * I18n for error messages
12
27
  * Rails: delete flash keys if unused
13
28
 
14
- == 0.3.4 / 2011-12-13
29
+ ## 0.3.4 / 2011-12-13
15
30
 
16
31
  * Rails 3
17
32
  * Remove jeweler
18
33
 
19
- == 0.2.2 / 2009-09-14
34
+ ## 0.2.2 / 2009-09-14
20
35
 
21
36
  * Add a timeout to the validator
22
37
  * Give the documentation some love
23
38
 
24
- == 0.2.1 / 2009-09-14
39
+ ## 0.2.1 / 2009-09-14
25
40
 
26
41
  * Removed Ambethia namespace, and restructured classes a bit
27
42
  * Added an example rails app in the example-rails branch
28
43
 
29
- == 0.2.0 / 2009-09-12
44
+ ## 0.2.0 / 2009-09-12
30
45
 
31
46
  * RecaptchaOptions AJAX API Fix
32
47
  * Added 'cucumber' as a test environment to skip
@@ -35,7 +50,7 @@
35
50
  * Removed dependency on ActiveRecord constant
36
51
  * Add I18n
37
52
 
38
- == 0.1.0 / 2008-2-8
53
+ ## 0.1.0 / 2008-2-8
39
54
 
40
55
  * 1 major enhancement
41
- * Initial Gem Release
56
+ * Initial Gem Release
data/README.md CHANGED
@@ -11,102 +11,56 @@ views you can use the `recaptcha_tags` method to embed the needed javascript,
11
11
  and you can validate in your controllers with `verify_recaptcha` or `verify_recaptcha!`,
12
12
  which throws an error on failiure.
13
13
 
14
- Beforehand you need to configure Recaptcha with your custom private and public
15
- key. You may find detailed examples below. Exceptions will be raised if you
16
- call these methods and the keys can't be found.
17
-
18
14
  ## Rails Installation
19
15
 
20
- ```Ruby
21
- gem "recaptcha", require: "recaptcha/rails"
22
- ```
23
-
24
- (Rails < 3.0: install an older release and view it's README)
25
-
26
- ## Setting up your API Keys
27
-
28
- There are multiple ways to setup your reCAPTCHA API key once you
29
- [obtain a pair](https://www.google.com/recaptcha/admin).
30
-
31
- ### Recaptcha.configure
32
-
33
- You may use the block style configuration. The following code could be placed
34
- into a `config/initializers/recaptcha.rb` when used in a Rails project.
35
-
36
- ```Ruby
37
- Recaptcha.configure do |config|
38
- config.public_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
39
- config.private_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
40
- # Uncomment the following line if you are using a proxy server:
41
- # config.proxy = 'http://myproxy.com.au:8080'
42
- # Uncomment if you want to use the older version of the API,
43
- # only works for versions >= 0.3.7, default value is 'v2':
44
- # config.api_version = 'v1'
45
- end
46
- ```
47
-
48
- This way, you may also set additional options to fit recaptcha into your
49
- deployment environment.
50
-
51
- ### Recaptcha.with_configuration
52
-
53
- If you want to temporarily overwrite the configuration you set with
54
- `Recaptcha.configure` (when testing, for example), you can use a
55
- `Recaptcha#with_configuration` block:
16
+ [obtain a reCAPTCHA API key](https://www.google.com/recaptcha/admin).
56
17
 
57
18
  ```Ruby
58
- Recaptcha.with_configuration(public_key: '12345') do
59
- # Do stuff with the overwritten public_key.
60
- end
19
+ gem "recaptcha", require: "recaptcha/rails"
61
20
  ```
62
21
 
63
- ### Heroku & Shell environment
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.
64
24
 
65
- Or, you can keep your keys out of your code base by exporting the following
66
- environment variables. You might do this in the .profile/rc, or equivalent for
67
- the user running your application. This would also be the preffered method
68
- in an Heroku deployment.
25
+ Otherwise see [Alternative API key setup](#alternative-api-key-setup).
69
26
 
70
27
  ```
71
28
  export RECAPTCHA_PUBLIC_KEY = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
72
29
  export RECAPTCHA_PRIVATE_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
73
30
  ```
74
31
 
75
- ### Per call
76
-
77
- You can also pass in your keys as options at runtime, for example:
32
+ Add `recaptcha_tags` to the forms you want to protect.
78
33
 
79
- ```Ruby
80
- recaptcha_tags public_key: '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
34
+ ```Erb
35
+ <%= form_for @foo do |f| %>
36
+ # ... other tags
37
+ <%= recaptcha_tags %>
38
+ # ... other tags
39
+ <% end %>
81
40
  ```
82
41
 
83
- and later,
42
+ And, add `verify_recaptcha` logic to each form action that you've protected.
84
43
 
85
44
  ```Ruby
86
- verify_recaptcha private_key: '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
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
87
52
  ```
88
53
 
89
- This option might be useful, if the same code base is used for multiple
90
- reCAPTCHA setups.
54
+ ## Sinatra / Rack / Ruby installation
91
55
 
92
- ## To use 'recaptcha'
56
+ See [sinatra demo](/demo/sinatra) for details.
93
57
 
94
- Add `recaptcha_tags` to each form you want to protect.
95
- Place it where you want the recaptcha widget to appear.
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`
96
62
 
97
- Example:
98
-
99
- ```Erb
100
- <%= form_for @foo do |f| %>
101
- # ... additional lines truncated for brevity ...
102
- <%= recaptcha_tags %>
103
- # ... additional lines truncated for brevity ...
104
- <% end %>
105
- ```
106
-
107
- And, add `verify_recaptcha` logic to each form action that you've protected.
108
-
109
- ### recaptcha_tags
63
+ ## recaptcha_tags
110
64
 
111
65
  Some of the options available:
112
66
 
@@ -116,16 +70,15 @@ Some of the options available:
116
70
  | :noscript | Include <noscript> content (default `true`)|
117
71
  | :display | Takes a hash containing the `theme` and `tabindex` options per the API. (default `nil`), options: 'red', 'white', 'blackglass', 'clean', 'custom'|
118
72
  | :ajax | Render the dynamic AJAX captcha per the API. (default `false`)|
119
- | :public_key | Your public API key, takes precedence over the ENV variable (default `nil`)|
73
+ | :public_key | Override public API key |
120
74
  | :error | Override the error code returned from the reCAPTCHA API (default `nil`)|
121
75
  | :stoken | Include in reCAPTCHA API v2 the security token (default `true`)|
122
76
  | :size | Specify a size (default `nil`)|
123
77
 
124
-
125
78
  You can also override the html attributes for the sizes of the generated `textarea` and `iframe`
126
79
  elements, if CSS isn't your thing. Inspect the source of `recaptcha_tags` to see these options.
127
80
 
128
- ### verify_recaptcha
81
+ ## verify_recaptcha
129
82
 
130
83
  This method returns `true` or `false` after processing the parameters from the reCAPTCHA widget. Why
131
84
  isn't this a model validation? Because that violates MVC. You can use it like this, or how ever you
@@ -139,135 +92,10 @@ Some of the options available:
139
92
  | :model | Model to set errors
140
93
  | :attribute | Model attribute to receive errors (default :base)
141
94
  | :message | Custom error message
142
- | :private_key | Your private API key, takes precedence over the ENV variable (default `nil`).
95
+ | :private_key | Override private API key.
143
96
  | :timeout | The number of seconds to wait for reCAPTCHA servers before give up. (default `3`)
97
+ | :response | Custom response parameter (default: params['g-recaptcha-response'])
144
98
 
145
- ```Ruby
146
- respond_to do |format|
147
- if verify_recaptcha(model @post, message: "Oh! It's error with reCAPTCHA!") && @post.save
148
- # ...
149
- else
150
- # ...
151
- end
152
- end
153
- ```
154
-
155
- ### Add multiple widgets to the same page
156
-
157
- This is an example taken from the [official google documentation](https://developers.google.com/recaptcha/docs/display).
158
-
159
- Add a script tag for a callback
160
-
161
- ```Html
162
- <script type="text/javascript">
163
- var verifyCallback = function(response) {
164
- alert(response);
165
- };
166
- var widgetId1;
167
- var widgetId2;
168
- var onloadCallback = function() {
169
- // Renders the HTML element with id 'example1' as a reCAPTCHA widget.
170
- // The id of the reCAPTCHA widget is assigned to 'widgetId1'.
171
- widgetId1 = grecaptcha.render('example1', {
172
- 'sitekey' : "<%= Recaptcha.configuration.public_key %>",
173
- 'theme' : 'light'
174
- });
175
- widgetId2 = grecaptcha.render(document.getElementById('example2'), {
176
- 'sitekey' : "<%= Recaptcha.configuration.public_key %>"
177
- });
178
- grecaptcha.render('example3', {
179
- 'sitekey' : "<%= Recaptcha.configuration.public_key %>",
180
- 'callback' : verifyCallback,
181
- 'theme' : 'dark'
182
- });
183
- };
184
- </script>
185
- ```
186
-
187
- In the callback you will have the `sitekey` generated by this gem with `<%= Recaptcha.configuration.public_key %>`
188
-
189
- Next you need to have some elements with an id matching those specified in the callback
190
-
191
- ```Erb
192
- <%= form_for @foo do |f| %>
193
- # ... additional lines truncated for brevity ...
194
- <div id="example1"></div>
195
- # ... additional lines truncated for brevity ...
196
- <% end %>
197
- <%= form_for @foo2 do |f| %>
198
- # ... additional lines truncated for brevity ...
199
- <div id="example2"></div>
200
- # ... additional lines truncated for brevity ...
201
- <% end %>
202
- <%= form_for @foo3 do |f| %>
203
- # ... additional lines truncated for brevity ...
204
- <div id="example3"></div>
205
- # ... additional lines truncated for brevity ...
206
- <% end %>
207
- ```
208
-
209
- And finally you need a script tag that gets the reCAPTCHA code from google and tells it that your code is explicit and gives it the callback.
210
-
211
- ```Html
212
- <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
213
- ```
214
-
215
- Now all together:
216
-
217
- ```Html
218
- <html>
219
- <head>
220
- <title>reCAPTCHA demo: Explicit render for multiple widgets</title>
221
- <script type="text/javascript">
222
- var verifyCallback = function(response) {
223
- alert(response);
224
- };
225
- var widgetId1;
226
- var widgetId2;
227
- var onloadCallback = function() {
228
- // Renders the HTML element with id 'example1' as a reCAPTCHA widget.
229
- // The id of the reCAPTCHA widget is assigned to 'widgetId1'.
230
- widgetId1 = grecaptcha.render('example1', {
231
- 'sitekey' : "<%= Recaptcha.configuration.public_key %>",
232
- 'theme' : 'light'
233
- });
234
- widgetId2 = grecaptcha.render(document.getElementById('example2'), {
235
- 'sitekey' : "<%= Recaptcha.configuration.public_key %>"
236
- });
237
- grecaptcha.render('example3', {
238
- 'sitekey' : "<%= Recaptcha.configuration.public_key %>",
239
- 'callback' : verifyCallback,
240
- 'theme' : 'dark'
241
- });
242
- };
243
- </script>
244
- </head>
245
- <body>
246
- <%= form_for @foo do |f| %>
247
- # ... additional lines truncated for brevity ...
248
- <div id="example1"></div>
249
- # ... additional lines truncated for brevity ...
250
- <% end %>
251
- <%= form_for @foo2 do |f| %>
252
- # ... additional lines truncated for brevity ...
253
- <div id="example2"></div>
254
- # ... additional lines truncated for brevity ...
255
- <% end %>
256
- <%= form_for @foo3 do |f| %>
257
- # ... additional lines truncated for brevity ...
258
- <div id="example3"></div>
259
- # ... additional lines truncated for brevity ...
260
- <% end %>
261
- <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
262
- </body>
263
- </html>
264
- ```
265
-
266
- The only real difference between this example and the google example is you will use the `<%= Recaptcha.configuration.public_key %>` for the `sitekey`
267
-
268
- If your callback has to live on another file (maybe a layout), then you would set the callback on window `window.onloadCallback = function() {...}`
269
-
270
- Then on the backend, you will still use the `verify_recaptcha` as explained in this readme.
271
99
 
272
100
  ## I18n support
273
101
  reCAPTCHA passes two types of error explanation to a linked model. It will use the I18n gem
@@ -287,9 +115,49 @@ en:
287
115
  ```
288
116
 
289
117
  ## Testing
290
- By default, reCAPTCHA is skipped on "test" env, so if you need to make sure it's working properly, just remove the "test" entry of the skip_environment inside Recapcha class, look:
291
118
 
119
+ By default, reCAPTCHA is skipped in "test" and "cucumber" env. To enable it during test:
292
120
 
293
121
  ```Ruby
294
122
  Recaptcha.configuration.skip_verify_env.delete("test")
295
123
  ```
124
+
125
+ ## Alternative API key setup
126
+
127
+ ### Recaptcha.configure
128
+
129
+ ```Ruby
130
+ # config/initializers/recaptcha.rb
131
+ Recaptcha.configure do |config|
132
+ config.public_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
133
+ config.private_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
134
+ # Uncomment the following line if you are using a proxy server:
135
+ # config.proxy = 'http://myproxy.com.au:8080'
136
+ end
137
+ ```
138
+
139
+ ### Recaptcha.with_configuration
140
+
141
+ For temporary overwrites (not thread safe).
142
+
143
+ ```Ruby
144
+ Recaptcha.with_configuration(public_key: '12345') do
145
+ # Do stuff with the overwritten public_key.
146
+ end
147
+ ```
148
+
149
+ ### Per call
150
+
151
+ Pass in keys as options at runtime, for code base with multiple reCAPTCHA setups:
152
+
153
+ ```Ruby
154
+ recaptcha_tags public_key: '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
155
+
156
+ and
157
+
158
+ verify_recaptcha private_key: '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
159
+ ```
160
+
161
+ ## Misc
162
+ - Check out the [wiki](https://github.com/ambethia/recaptcha/wiki) and leave whatever you found valuable there.
163
+ - [Add multiple widgets to the same page](https://github.com/ambethia/recaptcha/wiki/Add-multiple-widgets-to-the-same-page)
@@ -2,27 +2,19 @@ require 'recaptcha/configuration'
2
2
  require 'recaptcha/client_helper'
3
3
  require 'recaptcha/verify'
4
4
  require 'recaptcha/token'
5
+ require 'uri'
5
6
 
6
7
  module Recaptcha
7
- CONFIG =
8
- {
9
- 'v1' => {
10
- 'server_url' => '//www.google.com/recaptcha/api',
11
- 'secure_server_url' => 'https://www.google.com/recaptcha/api',
12
- 'verify_url' => 'http://www.google.com/recaptcha/api/verify'
13
- },
14
-
15
- 'v2' => {
16
- 'server_url' => '//www.google.com/recaptcha/api.js',
17
- 'secure_server_url' => 'https://www.google.com/recaptcha/api.js',
18
- 'verify_url' => 'https://www.google.com/recaptcha/api/siteverify'
19
- }
20
- }
21
-
22
- RECAPTCHA_API_VERSION = 'v2'
8
+ CONFIG = {
9
+ 'server_url' => '//www.google.com/recaptcha/api.js',
10
+ 'secure_server_url' => 'https://www.google.com/recaptcha/api.js',
11
+ 'verify_url' => 'https://www.google.com/recaptcha/api/siteverify'
12
+ }
13
+
23
14
  USE_SSL_BY_DEFAULT = false
24
15
  HANDLE_TIMEOUTS_GRACEFULLY = true
25
16
  SKIP_VERIFY_ENV = ['test', 'cucumber']
17
+ DEFAULT_TIMEOUT = 3
26
18
 
27
19
  # Gives access to the current Configuration.
28
20
  def self.configuration
@@ -54,6 +46,34 @@ module Recaptcha
54
46
  result
55
47
  end
56
48
 
49
+ def self.get(verify_hash, options)
50
+ http = if Recaptcha.configuration.proxy
51
+ proxy_server = URI.parse(Recaptcha.configuration.proxy)
52
+ Net::HTTP::Proxy(proxy_server.host, proxy_server.port, proxy_server.user, proxy_server.password)
53
+ else
54
+ Net::HTTP
55
+ end
56
+ query = URI.encode_www_form(verify_hash)
57
+ uri = URI.parse(Recaptcha.configuration.verify_url + '?' + query)
58
+ http_instance = http.new(uri.host, uri.port)
59
+ http_instance.read_timeout = http_instance.open_timeout = options[:timeout] || DEFAULT_TIMEOUT
60
+ if uri.port == 443
61
+ http_instance.use_ssl = true
62
+ http_instance.verify_mode = OpenSSL::SSL::VERIFY_NONE
63
+ end
64
+ request = Net::HTTP::Get.new(uri.request_uri)
65
+ http_instance.request(request).body
66
+ end
67
+
68
+ def self.i18n(key, default)
69
+ if defined?(I18n)
70
+ I18n.translate(key, default: default)
71
+ else
72
+ default
73
+ end
74
+ end
75
+
76
+
57
77
  class RecaptchaError < StandardError
58
78
  end
59
79
 
@@ -3,129 +3,50 @@ module Recaptcha
3
3
  # Your public API can be specified in the +options+ hash or preferably
4
4
  # using the Configuration.
5
5
  def recaptcha_tags(options = {})
6
- return v1_tags(options) if Recaptcha.configuration.v1?
7
- return v2_tags(options) if Recaptcha.configuration.v2?
8
- end # recaptcha_tags
6
+ public_key = options[:public_key] || Recaptcha.configuration.public_key!
9
7
 
10
- def v1_tags(options)
11
- # Default options
12
- key = options[:public_key] ||= Recaptcha.configuration.public_key
13
- raise RecaptchaError, "No public key specified." unless key
14
- error = options[:error] ||= ((defined? flash) ? flash[:recaptcha_error] : "")
15
- uri = Recaptcha.configuration.api_server_url(options[:ssl])
16
- lang = options[:display] && options[:display][:lang] ? options[:display][:lang].to_sym : ""
17
- html = ""
18
- if options[:display]
19
- html << %{<script type="text/javascript">\n}
20
- html << %{ var RecaptchaOptions = #{hash_to_json(options[:display])};\n}
21
- html << %{</script>\n}
22
- end
23
- if options[:ajax]
24
- if options[:display] && options[:display][:custom_theme_widget]
25
- widget = options[:display][:custom_theme_widget]
26
- else
27
- widget = "dynamic_recaptcha"
28
- html << <<-EOS
29
- <div id="#{widget}"></div>
30
- EOS
31
- end
32
- html << <<-EOS
33
- <script type="text/javascript">
34
- var rc_script_tag = document.createElement('script'),
35
- rc_init_func = function(){Recaptcha.create("#{key}", document.getElementById("#{widget}")#{',RecaptchaOptions' if options[:display]});}
36
- rc_script_tag.src = "#{uri}/js/recaptcha_ajax.js";
37
- rc_script_tag.type = 'text/javascript';
38
- rc_script_tag.onload = function(){rc_init_func.call();};
39
- rc_script_tag.onreadystatechange = function(){
40
- if (rc_script_tag.readyState == 'loaded' || rc_script_tag.readyState == 'complete') {rc_init_func.call();}
41
- };
42
- (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(rc_script_tag);
43
- </script>
44
- EOS
45
- else
46
- html << %{<script type="text/javascript" src="#{uri}/challenge?k=#{key}}
47
- html << %{#{error ? "&amp;error=#{CGI::escape(error)}" : ""}}
48
- html << %{#{lang ? "&amp;lang=#{lang}" : ""}"></script>\n}
49
- unless options[:noscript] == false
50
- html << %{<noscript>\n }
51
- html << %{<iframe src="#{uri}/noscript?k=#{key}" }
52
- html << %{height="#{options[:iframe_height] ||= 300}" }
53
- html << %{width="#{options[:iframe_width] ||= 500}" }
54
- html << %{style="border:none;"></iframe><br/>\n }
55
- html << %{<textarea name="recaptcha_challenge_field" }
56
- html << %{rows="#{options[:textarea_rows] ||= 3}" }
57
- html << %{cols="#{options[:textarea_cols] ||= 40}"></textarea>\n }
58
- html << %{<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>}
59
- html << %{</noscript>\n}
60
- end
61
- end
62
- return (html.respond_to?(:html_safe) && html.html_safe) || html
63
- end
64
-
65
- def v2_tags(options)
66
- public_key = options[:public_key] ||= Recaptcha.configuration.public_key
67
- raise RecaptchaError, "No public key specified." unless public_key
68
- private_key = options[:private_key] ||= Recaptcha.configuration.private_key
69
- raise RecaptchaError, "No private key specified." unless private_key
70
- error = options[:error] ||= ((defined? flash) ? flash[:recaptcha_error] : "") # TODO not being used !?
71
- uri = Recaptcha.configuration.api_server_url(options[:ssl])
72
- uri += "?hl=#{options[:hl]}" unless options[:hl].blank?
73
-
74
- html = ""
75
- html << %{<script src="#{uri}" async defer></script>\n}
76
-
77
- data_attributes = options.slice(:theme, :type, :callback, :expired_callback, :size)
78
- data_attributes[:sitekey] = public_key
8
+ script_url = Recaptcha.configuration.api_server_url(ssl: options[:ssl])
9
+ script_url += "?hl=#{options[:hl]}" unless options[:hl].to_s == ""
10
+ fallback_uri = "#{script_url.chomp('.js')}/fallback?k=#{public_key}"
79
11
 
80
- if options[:stoken] != false
81
- data_attributes[:stoken] = Recaptcha::Token.secure_token
12
+ data_attributes = [:theme, :type, :callback, :expired_callback, :size]
13
+ data_attributes = options.each_with_object({}) do |(k, v), a|
14
+ a[k] = v if data_attributes.include?(k)
82
15
  end
16
+ data_attributes[:sitekey] = public_key
17
+ data_attributes[:stoken] = Recaptcha::Token.secure_token if options[:stoken] != false
18
+ data_attributes = data_attributes.map { |k,v| %{data-#{k.to_s.tr('_','-')}="#{v}"} }.join(" ")
83
19
 
84
- data_attributes = data_attributes.map {|k,v| %{data-#{k.to_s.gsub(/_/,'-')}="#{v}"} }.join(" ")
85
-
20
+ html = %{<script src="#{script_url}" async defer></script>\n}
86
21
  html << %{<div class="g-recaptcha" #{data_attributes}></div>\n}
87
22
 
88
- unless options[:noscript] == false
89
- fallback_uri = "#{uri.chomp('.js')}/fallback?k=#{public_key}"
90
- html << %{<noscript>}
91
- html << %{<div style="width: 302px; height: 352px;">}
92
- html << %{ <div style="width: 302px; height: 352px; position: relative;">}
93
- html << %{ <div style="width: 302px; height: 352px; position: absolute;">}
94
- html << %{ <iframe src="#{fallback_uri}"}
95
- html << %{ frameborder="0" scrolling="no"}
96
- html << %{ style="width: 302px; height:352px; border-style: none;">}
97
- html << %{ </iframe>}
98
- html << %{ </div>}
99
- html << %{ <div style="width: 250px; height: 80px; position: absolute; border-style: none; }
100
- html << %{ bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;">}
101
- html << %{ <textarea id="g-recaptcha-response" name="g-recaptcha-response" }
102
- html << %{ class="g-recaptcha-response" }
103
- html << %{ style="width: 250px; height: 80px; border: 1px solid #c1c1c1; }
104
- html << %{ margin: 0px; padding: 0px; resize: none;" value=""> }
105
- html << %{ </textarea>}
106
- html << %{ </div>}
107
- html << %{ </div>}
108
- html << %{ </div>}
109
- html << %{</noscript>}
23
+ if options[:noscript] != false
24
+ html << <<-HTML
25
+ <noscript>
26
+ <div style="width: 302px; height: 352px;">
27
+ <div style="width: 302px; height: 352px; position: relative;">
28
+ <div style="width: 302px; height: 352px; position: absolute;">
29
+ <iframe
30
+ src="#{fallback_uri}"
31
+ frameborder="0" scrolling="no"
32
+ style="width: 302px; height:352px; border-style: none;">
33
+ </iframe>
34
+ </div>
35
+ <div style="width: 250px; height: 80px; position: absolute; border-style: none;
36
+ bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;">
37
+ <textarea id="g-recaptcha-response" name="g-recaptcha-response"
38
+ class="g-recaptcha-response"
39
+ style="width: 250px; height: 80px; border: 1px solid #c1c1c1;
40
+ margin: 0px; padding: 0px; resize: none;" value="">
41
+ </textarea>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </noscript>
46
+ HTML
110
47
  end
111
48
 
112
- (html.respond_to?(:html_safe) && html.html_safe) || html
113
- end
114
-
115
- private
116
-
117
- def hash_to_json(hash)
118
- result = "{"
119
- result << hash.map do |k, v|
120
- if v.is_a?(Hash)
121
- "\"#{k}\": #{hash_to_json(v)}"
122
- elsif ! v.is_a?(String) || k.to_s =~ %r{(callback|expired-callback)}
123
- "\"#{k}\": #{v}"
124
- else
125
- "\"#{k}\": \"#{v}\""
126
- end
127
- end.join(", ")
128
- result << "}"
49
+ html.respond_to?(:html_safe) ? html.html_safe : html
129
50
  end
130
51
  end
131
52
  end
@@ -28,47 +28,33 @@ module Recaptcha
28
28
  # end
29
29
  #
30
30
  class Configuration
31
- attr_accessor :api_version,
32
- :skip_verify_env,
33
- :private_key,
34
- :public_key,
35
- :proxy,
36
- :handle_timeouts_gracefully,
37
- :use_ssl_by_default
31
+ attr_accessor :skip_verify_env, :private_key, :public_key, :proxy, :handle_timeouts_gracefully, :use_ssl_by_default
38
32
 
39
33
  def initialize #:nodoc:
40
- @api_version = RECAPTCHA_API_VERSION
41
34
  @skip_verify_env = SKIP_VERIFY_ENV
42
35
  @handle_timeouts_gracefully = HANDLE_TIMEOUTS_GRACEFULLY
43
36
  @use_ssl_by_default = USE_SSL_BY_DEFAULT
44
37
 
45
38
  @private_key = ENV['RECAPTCHA_PRIVATE_KEY']
46
- @public_key = ENV['RECAPTCHA_PUBLIC_KEY']
39
+ @public_key = ENV['RECAPTCHA_PUBLIC_KEY']
47
40
  end
48
41
 
49
- def api_server_url(ssl = nil) #:nodoc:
50
- ssl = use_ssl_by_default if ssl.nil?
51
- ssl ? ssl_api_server_url : nonssl_api_server_url
42
+ def private_key!
43
+ private_key || raise(RecaptchaError, "No private key specified.")
52
44
  end
53
45
 
54
- def nonssl_api_server_url
55
- CONFIG[@api_version]['server_url']
46
+ def public_key!
47
+ public_key || raise(RecaptchaError, "No public key specified.")
56
48
  end
57
49
 
58
- def ssl_api_server_url
59
- CONFIG[@api_version]['secure_server_url']
50
+ def api_server_url(ssl: nil)
51
+ ssl = use_ssl_by_default if ssl.nil?
52
+ key = (ssl ? 'secure_server_url' : 'server_url')
53
+ CONFIG.fetch(key)
60
54
  end
61
55
 
62
56
  def verify_url
63
- CONFIG[@api_version]['verify_url']
64
- end
65
-
66
- def v1?
67
- @api_version == 'v1'
68
- end
69
-
70
- def v2?
71
- @api_version == 'v2'
57
+ CONFIG.fetch('verify_url')
72
58
  end
73
59
  end
74
60
  end
@@ -1,101 +1,53 @@
1
- require "uri"
2
- require "json"
1
+ require 'json'
3
2
 
4
3
  module Recaptcha
5
4
  module Verify
6
- DEFAULT_TIMEOUT = 3
7
-
8
5
  # Your private API can be specified in the +options+ hash or preferably
9
6
  # using the Configuration.
10
7
  def verify_recaptcha(options = {})
11
8
  options = {:model => options} unless options.is_a? Hash
12
-
13
- env_options = options[:env] || ENV['RAILS_ENV'] || (Rails.env if defined? Rails.env)
14
- return true if Recaptcha.configuration.skip_verify_env.include? env_options
15
9
  model = options[:model]
16
10
  attribute = options[:attribute] || :base
17
- private_key = options[:private_key] || Recaptcha.configuration.private_key
18
- raise RecaptchaError, "No private key specified." unless private_key
19
11
 
20
- begin
21
- recaptcha = nil
22
- if Recaptcha.configuration.proxy
23
- proxy_server = URI.parse(Recaptcha.configuration.proxy)
24
- http = Net::HTTP::Proxy(proxy_server.host, proxy_server.port, proxy_server.user, proxy_server.password)
25
- else
26
- http = Net::HTTP
27
- end
12
+ return true if Recaptcha::Verify.skip?(options[:env])
13
+
14
+ private_key = options[:private_key] || Recaptcha.configuration.private_key!
15
+ recaptcha_response = options[:response] || params['g-recaptcha-response'].to_s
28
16
 
17
+ begin
29
18
  # env['REMOTE_ADDR'] to retrieve IP for Grape API
30
19
  remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
31
- if Recaptcha.configuration.v1?
32
- verify_hash = {
33
- "privatekey" => private_key,
34
- "remoteip" => remote_ip,
35
- "challenge" => params[:recaptcha_challenge_field],
36
- "response" => params[:recaptcha_response_field]
37
- }
38
- Timeout::timeout(options[:timeout] || DEFAULT_TIMEOUT) do
39
- recaptcha = http.post_form(URI.parse(Recaptcha.configuration.verify_url), verify_hash)
40
- end
41
- answer, error = recaptcha.body.split.map { |s| s.chomp }
42
- end
20
+ verify_hash = {
21
+ "secret" => private_key,
22
+ "remoteip" => remote_ip.to_s,
23
+ "response" => recaptcha_response
24
+ }
43
25
 
44
- if Recaptcha.configuration.v2?
45
- verify_hash = {
46
- "secret" => private_key,
47
- "remoteip" => remote_ip,
48
- "response" => params['g-recaptcha-response']
49
- }
50
-
51
- Timeout::timeout(options[:timeout] || DEFAULT_TIMEOUT) do
52
- uri = URI.parse(Recaptcha.configuration.verify_url + '?' + verify_hash.to_query)
53
- http_instance = http.new(uri.host, uri.port)
54
- if uri.port == 443
55
- http_instance.use_ssl =
56
- http_instance.verify_mode = OpenSSL::SSL::VERIFY_NONE
57
- end
58
- request = Net::HTTP::Get.new(uri.request_uri)
59
- recaptcha = http_instance.request(request)
60
- end
61
- answer, error = JSON.parse(recaptcha.body).values
62
- end
26
+ reply = Recaptcha.get(verify_hash, options)
27
+ answer = JSON.parse(reply)['success']
63
28
 
64
29
  if answer.to_s == 'true'
65
- flash.delete(:recaptcha_error) if request_in_html_format?
30
+ flash.delete(:recaptcha_error) if recaptcha_flash_supported?
66
31
  true
67
32
  else
68
- error = 'verification_failed' if error && Recaptcha.configuration.v2?
69
- if request_in_html_format?
70
- flash[:recaptcha_error] = if defined?(I18n)
71
- I18n.translate("recaptcha.errors.#{error}", default: error)
72
- else
73
- error
74
- end
75
- end
76
-
77
- if model
78
- message = "Word verification response is incorrect, please try again."
79
- message = I18n.translate('recaptcha.errors.verification_failed', default: message) if defined?(I18n)
80
- model.errors.add attribute, options[:message] || message
81
- end
33
+ recaptcha_error(
34
+ model,
35
+ attribute,
36
+ options[:message],
37
+ "recaptcha.errors.verification_failed",
38
+ "Word verification response is incorrect, please try again."
39
+ )
82
40
  false
83
41
  end
84
42
  rescue Timeout::Error
85
43
  if Recaptcha.configuration.handle_timeouts_gracefully
86
- if request_in_html_format?
87
- flash[:recaptcha_error] = if defined?(I18n)
88
- I18n.translate('recaptcha.errors.recaptcha_unreachable', default: 'Recaptcha unreachable.')
89
- else
90
- 'Recaptcha unreachable.'
91
- end
92
- end
93
-
94
- if model
95
- message = "Oops, we failed to validate your word verification response. Please try again."
96
- message = I18n.translate('recaptcha.errors.recaptcha_unreachable', default: message) if defined?(I18n)
97
- model.errors.add attribute, options[:message] || message
98
- end
44
+ recaptcha_error(
45
+ model,
46
+ attribute,
47
+ options[:message],
48
+ "recaptcha.errors.recaptcha_unreachable",
49
+ "Oops, we failed to validate your word verification response. Please try again."
50
+ )
99
51
  false
100
52
  else
101
53
  raise RecaptchaError, "Recaptcha unreachable."
@@ -105,12 +57,25 @@ module Recaptcha
105
57
  end
106
58
  end
107
59
 
108
- def request_in_html_format?
60
+ def verify_recaptcha!(options = {})
61
+ verify_recaptcha(options) or raise VerifyError
62
+ end
63
+
64
+ private
65
+
66
+ def recaptcha_error(model, attribute, message, key, default)
67
+ message = message || Recaptcha.i18n(key, default)
68
+ flash[:recaptcha_error] = message if recaptcha_flash_supported?
69
+ model.errors.add attribute, message if model
70
+ end
71
+
72
+ def recaptcha_flash_supported?
109
73
  request.respond_to?(:format) && request.format == :html && respond_to?(:flash)
110
74
  end
111
75
 
112
- def verify_recaptcha!(options = {})
113
- verify_recaptcha(options) or raise VerifyError
76
+ def self.skip?(env)
77
+ env ||= ENV['RAILS_ENV'] || (Rails.env if defined? Rails.env)
78
+ Recaptcha.configuration.skip_verify_env.include? env
114
79
  end
115
80
  end
116
81
  end
@@ -1,3 +1,3 @@
1
1
  module Recaptcha
2
- VERSION = "0.6.0"
2
+ VERSION = "1.0.0"
3
3
  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: 0.6.0
4
+ version: 1.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: 2015-11-19 00:00:00.000000000 Z
11
+ date: 2015-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: Helpers for the reCAPTCHA API
126
140
  email:
127
141
  - jasper@ambethia.com
@@ -129,7 +143,7 @@ executables: []
129
143
  extensions: []
130
144
  extra_rdoc_files: []
131
145
  files:
132
- - CHANGELOG
146
+ - CHANGELOG.md
133
147
  - LICENSE
134
148
  - README.md
135
149
  - lib/recaptcha.rb