re_captcha 0.1.2 → 0.2.1
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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -3
- data/Gemfile +0 -3
- data/README.md +98 -9
- data/Rakefile +1 -0
- data/lib/re_captcha/application.rb +0 -1
- data/lib/re_captcha/helpers.rb +1 -7
- data/lib/re_captcha/version.rb +1 -1
- data/re_captcha.gemspec +4 -4
- data/spec/re_captcha/client_spec.rb +2 -2
- metadata +19 -22
- data/lib/re_captcha/secure_token_builder.rb +0 -45
- data/spec/re_captcha/secure_token_builder_spec.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81a6ae75233a99302c6f73f367400f81bc2640e7
|
4
|
+
data.tar.gz: 04ccf3ce59845889bdeeb81dc03ddbd57c924885
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd082fda23e52c2703d885b634a16d10e9fb02ba1c9d4f3454f79bd3e917eef759e3b62ebac784493d74945f454233890910a0d6342ba2982cc8557c2a01f9d8
|
7
|
+
data.tar.gz: fa807cf8aecf83e50ddaa3df6ae2b08c10d2225e8802653bd0855b61a3f5d419d4644a51c366c40072c586cba8aa590fdf2927d7f3095898cb128b42300b174f
|
data/.travis.yml
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
-
|
4
|
-
-
|
5
|
-
|
3
|
+
- 2.4.4
|
4
|
+
- 2.5.3
|
5
|
+
|
6
|
+
notifications:
|
7
|
+
flowdock:
|
8
|
+
secure: nK6d4SB5Ys3CBqoeavpDP60nc9m6pIcs8Bfxl07h9umYpUnY26irCY70g3kqXbR0tOj/KVaaXyuzwmYv9T+xAKNoNjaByM8xh4XLcvA/AE57q18wYrH4ttr9yRcw0pLSjvJCVD5+SiE39nplH/khOWTCsw2bO80/WZ1l9ixP6kbSTnAg7uxvSMaEPckNn76/0t7S1OLtHeTL8xUra0XUiC6rzuadg463uQa8TDxSbFfEQ4QRR+e/SyXHOXCaDjJqm9/FSGkN1A4VB3lCFshfZIP9prpQ145IpVDIfou3tkmajDGysKf3raBT6Xqa9LUzTfetvmufvyHUZDgBUwgAH5rRzquDo3yrnzY7fJ/LCorElg5odPstRbh7mKAJrel0WGys4gpCKv8WgekOKd+OLGxhClvd3Y28sol7AqKDZXIoHLOd8p5hzlzrquhLD3k0IrHivRHXmloqUSddrO28/HIVCgVYoUN/UNojPaFBgGqa6KrCmzSLda2m0j81QdcDhgH0NOWar5L460sdvoVgDC2hKKEnbJLkvdEzt3I0ZXIxeYMsF46LtkXuY7Xmg8/h+Oy4aJDBdakmwqrGejIaokf/3AybR1kP+brC0voSt0EwaDZ0AztONq0gYxu9gJrpSPwE/pOHQWe2iWnSXEiGVM297kbPSunEF6TCYWcdoOE=
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# ReCaptcha
|
2
2
|
|
3
|
-
|
3
|
+
[](https://travis-ci.org/textmaster/re_captcha)
|
4
|
+
[](https://codeclimate.com/github/textmaster/re_captcha)
|
5
|
+
|
6
|
+
Gem to easily use [Google reCaptcha](https://www.google.com/recaptcha/)
|
7
|
+
|
8
|
+
The gem implements v2 of the reCaptcha API.
|
4
9
|
|
5
10
|
Run tests with ``` rake ```
|
6
11
|
|
@@ -10,7 +15,7 @@ Run console with preloaded library with ``` rake console ```
|
|
10
15
|
|
11
16
|
You may need to configure the gem with non default values:
|
12
17
|
|
13
|
-
```
|
18
|
+
```ruby
|
14
19
|
ReCaptcha.configure do |config|
|
15
20
|
config.private_key = "secret key"
|
16
21
|
config.public_key = "site key"
|
@@ -19,16 +24,16 @@ end
|
|
19
24
|
```
|
20
25
|
|
21
26
|
The options are:
|
22
|
-
- private_key (default: ENV['RECAPTCHA_PRIVATE_KEY'])
|
23
|
-
- public_key (default: ENV['RECAPTCHA_PUBLIC_KEY'])
|
24
|
-
- api_endpoint (default: https://www.google.com/recaptcha/)
|
25
|
-
- skipped_env (default: ['test', 'cucumber'])
|
26
|
-
- language_table
|
27
|
-
- deny_on_error
|
27
|
+
- `private_key` (default: `ENV['RECAPTCHA_PRIVATE_KEY']`)
|
28
|
+
- `public_key` (default: `ENV['RECAPTCHA_PUBLIC_KEY']`)
|
29
|
+
- `api_endpoint` (default: https://www.google.com/recaptcha/)
|
30
|
+
- `skipped_env` (default: `['test', 'cucumber']`)
|
31
|
+
- `language_table`: the table to map locale with language code
|
32
|
+
- `deny_on_error`: if the Google reCaptcha API can't be accessed, deny the verification (default: `false`)
|
28
33
|
|
29
34
|
The default language table is the following:
|
30
35
|
|
31
|
-
```
|
36
|
+
```ruby
|
32
37
|
{
|
33
38
|
'en-US' => 'en',
|
34
39
|
'fr-FR' => 'fr',
|
@@ -64,11 +69,95 @@ The options are the following (the default value is given):
|
|
64
69
|
|
65
70
|
Check the reCaptcha doc for the available values (https://developers.google.com/recaptcha/docs/display).
|
66
71
|
|
72
|
+
Here is an example that shows how to use the helpers in a view (haml)
|
73
|
+
```ruby
|
74
|
+
- content_for :scripts do
|
75
|
+
= recaptcha_script(language: I18n.locale)
|
76
|
+
|
77
|
+
...
|
78
|
+
|
79
|
+
= form_for @object, url: my_path, method: :post, html: { class: 'form' } do |form|
|
80
|
+
= form.text_area :message, placeholder: 'Message'
|
81
|
+
= recaptcha_tags
|
82
|
+
= form.submit 'Submit', class: 'submit btn blue-bg anim'
|
83
|
+
```
|
84
|
+
|
67
85
|
## Verification
|
68
86
|
|
69
87
|
Assuming that your application uses Rails, verify the reCaptcha response in your controller using the method ```recaptcha_valid?(model: nil, message: nil)```.
|
70
88
|
|
71
89
|
model and message are optional and enables you to set an error message on the :base attribute of the provided model.
|
72
90
|
|
91
|
+
Example
|
92
|
+
```ruby
|
93
|
+
def create
|
94
|
+
@user = User.new(user_params)
|
95
|
+
|
96
|
+
return error(t('invalid_recaptcha')) unless recaptcha_valid?
|
97
|
+
|
98
|
+
if @user.save
|
99
|
+
redirect_to root_path
|
100
|
+
else
|
101
|
+
error(t('user_error'))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def error(message)
|
108
|
+
flash[:error] = message
|
109
|
+
render :new
|
110
|
+
end
|
111
|
+
```
|
73
112
|
|
74
113
|
If you're not using Rails, this method can be called like this: ```ReCaptcha.client.recaptcha_valid?(response, remote_ip: nil)```. No model nor message can be provided.
|
114
|
+
|
115
|
+
## Integration with devise
|
116
|
+
|
117
|
+
- Get your keys from [Google reCaptcha](https://www.google.com/recaptcha/). The site key is the public key and the secret is the secret one.
|
118
|
+
- Install this gem
|
119
|
+
```ruby
|
120
|
+
# Gemfile
|
121
|
+
gem 're_captcha'
|
122
|
+
```
|
123
|
+
- Add the tags in your views. ```recaptcha_script``` may be added in your layout view.
|
124
|
+
```
|
125
|
+
<%= recaptcha_script(...) %>
|
126
|
+
|
127
|
+
...
|
128
|
+
|
129
|
+
<%= recaptcha_tags(...) %>
|
130
|
+
```
|
131
|
+
- Create your own controllers that inherit from the Devise controllers.
|
132
|
+
- For unlocks
|
133
|
+
```ruby
|
134
|
+
class UnlocksController < Devise::UnlocksController
|
135
|
+
def create
|
136
|
+
if recaptcha_valid?
|
137
|
+
super
|
138
|
+
else
|
139
|
+
self.resource = resource_class.find_or_initialize_with_errors(resource_class.unlock_keys, resource_params, :not_found)
|
140
|
+
flash[:error] = t("invalid_recaptcha")
|
141
|
+
render :new
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
```
|
147
|
+
- For passwords
|
148
|
+
```ruby
|
149
|
+
class PasswordsController < Devise::PasswordsController
|
150
|
+
def create
|
151
|
+
if recaptcha_valid?
|
152
|
+
super
|
153
|
+
else
|
154
|
+
self.resource = resource_class.find_or_initialize_with_errors(resource_class.unlock_keys, resource_params, :not_found)
|
155
|
+
flash[:error] = t("invalid_recaptcha")
|
156
|
+
render :new
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
```
|
161
|
+
- etc
|
162
|
+
|
163
|
+
Other examples are given on the [Devise Wiki](https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise) for [Recaptcha Gem](https://github.com/ambethia/recaptcha). The use case is similar and examples can be easily adapted.
|
data/Rakefile
CHANGED
data/lib/re_captcha/helpers.rb
CHANGED
@@ -3,7 +3,7 @@ module ReCaptcha
|
|
3
3
|
def recaptcha_tags(options = {})
|
4
4
|
html = ''
|
5
5
|
html << %(<div class="g-recaptcha" data-sitekey="#{ReCaptcha.client.public_key}" )
|
6
|
-
html << %(
|
6
|
+
html << %(#{tag_attributes(options)}></div>\n)
|
7
7
|
format_html(html)
|
8
8
|
end
|
9
9
|
|
@@ -19,12 +19,6 @@ module ReCaptcha
|
|
19
19
|
html.respond_to?(:html_safe) ? html.html_safe : html
|
20
20
|
end
|
21
21
|
|
22
|
-
def secure_token
|
23
|
-
private_key = ReCaptcha.client.private_key
|
24
|
-
secure_token_builder = SecureTokenBuilder.new(private_key)
|
25
|
-
secure_token_builder.build
|
26
|
-
end
|
27
|
-
|
28
22
|
def tag_attributes(theme: 'light', type: 'image', size: 'normal',
|
29
23
|
tab_index: 0, callback: nil, expired_callback: nil)
|
30
24
|
attributes = ''
|
data/lib/re_captcha/version.rb
CHANGED
data/re_captcha.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require File.expand_path('../lib/re_captcha/version', __FILE__)
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
|
-
gem.add_development_dependency 'rspec'
|
5
|
-
gem.add_development_dependency 'bundler'
|
6
|
-
gem.add_development_dependency 'rake'
|
7
|
-
gem.add_development_dependency 'webmock'
|
4
|
+
gem.add_development_dependency 'rspec'
|
5
|
+
gem.add_development_dependency 'bundler'
|
6
|
+
gem.add_development_dependency 'rake'
|
7
|
+
gem.add_development_dependency 'webmock'
|
8
8
|
|
9
9
|
gem.name = 're_captcha'
|
10
10
|
gem.summary = 'reCaptcha helpers'
|
@@ -127,7 +127,7 @@ describe ReCaptcha::Client do
|
|
127
127
|
context 'with a correct response' do
|
128
128
|
|
129
129
|
before(:all) do
|
130
|
-
body = { 'remoteip' =>
|
130
|
+
body = { 'remoteip' => nil, 'response' => 'correct response', 'secret' => 'bar' }
|
131
131
|
stub_request(:post, 'https://www.google.com/recaptcha/api/siteverify')
|
132
132
|
.with(body: body)
|
133
133
|
.to_return(status: 200, body: { success: true }.to_json)
|
@@ -143,7 +143,7 @@ describe ReCaptcha::Client do
|
|
143
143
|
context 'with an incorrect response' do
|
144
144
|
|
145
145
|
before(:all) do
|
146
|
-
body = { 'remoteip' =>
|
146
|
+
body = { 'remoteip' => nil, 'response' => 'incorrect response', 'secret' => 'bar' }
|
147
147
|
stub_request(:post, 'https://www.google.com/recaptcha/api/siteverify')
|
148
148
|
.with(body: body)
|
149
149
|
.to_return(status: 200, body: { success: false }.to_json)
|
metadata
CHANGED
@@ -1,71 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: re_captcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Jeusette
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: webmock
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
description: Google reCaptcha helpers and verifier
|
70
70
|
email:
|
71
71
|
- david@textmaster.com
|
@@ -91,13 +91,11 @@ files:
|
|
91
91
|
- lib/re_captcha/exceptions.rb
|
92
92
|
- lib/re_captcha/helpers.rb
|
93
93
|
- lib/re_captcha/rails/helpers.rb
|
94
|
-
- lib/re_captcha/secure_token_builder.rb
|
95
94
|
- lib/re_captcha/version.rb
|
96
95
|
- re_captcha.gemspec
|
97
96
|
- spec/re_captcha/client_spec.rb
|
98
97
|
- spec/re_captcha/configuration_spec.rb
|
99
98
|
- spec/re_captcha/helpers_spec.rb
|
100
|
-
- spec/re_captcha/secure_token_builder_spec.rb
|
101
99
|
- spec/re_captcha_spec.rb
|
102
100
|
- spec/spec_helper.rb
|
103
101
|
homepage: https://github.com/textmaster/re_captcha
|
@@ -120,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
118
|
version: '0'
|
121
119
|
requirements: []
|
122
120
|
rubyforge_project:
|
123
|
-
rubygems_version: 2.
|
121
|
+
rubygems_version: 2.6.14.1
|
124
122
|
signing_key:
|
125
123
|
specification_version: 4
|
126
124
|
summary: reCaptcha helpers
|
@@ -128,6 +126,5 @@ test_files:
|
|
128
126
|
- spec/re_captcha/client_spec.rb
|
129
127
|
- spec/re_captcha/configuration_spec.rb
|
130
128
|
- spec/re_captcha/helpers_spec.rb
|
131
|
-
- spec/re_captcha/secure_token_builder_spec.rb
|
132
129
|
- spec/re_captcha_spec.rb
|
133
130
|
- spec/spec_helper.rb
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'securerandom'
|
3
|
-
require 'openssl'
|
4
|
-
require 'base64'
|
5
|
-
|
6
|
-
module ReCaptcha
|
7
|
-
class SecureTokenBuilder
|
8
|
-
def initialize(private_key)
|
9
|
-
@private_key = private_key
|
10
|
-
end
|
11
|
-
|
12
|
-
def build
|
13
|
-
json_token = generate_json_token
|
14
|
-
private_key_digest = digest_key @private_key
|
15
|
-
cipher = prepare_cipher private_key_digest
|
16
|
-
encode_token json_token, cipher
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def encode_token(token, cipher)
|
22
|
-
encrypted_token = cipher.update(token) << cipher.final
|
23
|
-
strip_padding Base64.urlsafe_encode64(encrypted_token)
|
24
|
-
end
|
25
|
-
|
26
|
-
def digest_key(key)
|
27
|
-
Digest::SHA1.digest(key)[0...16]
|
28
|
-
end
|
29
|
-
|
30
|
-
def prepare_cipher(key)
|
31
|
-
cipher = OpenSSL::Cipher::AES128.new(:ECB)
|
32
|
-
cipher.encrypt
|
33
|
-
cipher.key = key
|
34
|
-
cipher
|
35
|
-
end
|
36
|
-
|
37
|
-
def generate_json_token
|
38
|
-
{ session_id: SecureRandom.uuid, ts_ms: (Time.now.to_f * 1000).to_i }.to_json
|
39
|
-
end
|
40
|
-
|
41
|
-
def strip_padding(string)
|
42
|
-
string.gsub(/\=+\Z/, '')
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ReCaptcha::SecureTokenBuilder do
|
4
|
-
let(:key) { 'my secret key' }
|
5
|
-
let(:instance) { described_class.new(key)}
|
6
|
-
|
7
|
-
describe 'instance' do
|
8
|
-
it { expect(instance).to respond_to(:build) }
|
9
|
-
|
10
|
-
describe '#build' do
|
11
|
-
|
12
|
-
it 'builds a secure token' do
|
13
|
-
expect(instance.build).to be_a(String)
|
14
|
-
expect(instance.build).not_to be_empty
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'builds a token with a correct value' do
|
18
|
-
time = Time.parse("Feb 24 1981")
|
19
|
-
allow(Time).to receive(:now).and_return(time)
|
20
|
-
allow(SecureRandom).to receive(:uuid).and_return('8a180d31-c031-4258-a36f-bc4207f67bef')
|
21
|
-
expect(instance.build).to eq("95ZHArcXmvPlPBc6r95vSj_83vWuXuetY9KfVy4O6AszqvTE_ok6u85L74jMQYmYKtIEqjOJzUgiK9kSjEROQYHleYCsftaXldeLgxeQCFI")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|