invisible_captcha 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +13 -2
- data/Appraisals +11 -0
- data/LICENSE +1 -1
- data/README.md +41 -66
- data/gemfiles/rails_3.2.gemfile +7 -0
- data/gemfiles/rails_4.1.gemfile +7 -0
- data/gemfiles/rails_4.2.gemfile +7 -0
- data/invisible_captcha.gemspec +5 -2
- data/lib/invisible_captcha.rb +2 -3
- data/lib/invisible_captcha/controller_ext.rb +13 -7
- data/lib/invisible_captcha/railtie.rb +1 -3
- data/lib/invisible_captcha/version.rb +1 -1
- data/spec/controllers_spec.rb +31 -12
- data/spec/dummy/app/controllers/topics_controller.rb +5 -0
- data/spec/dummy/app/models/topic.rb +0 -1
- data/spec/dummy/config/environments/development.rb +1 -1
- data/spec/dummy/config/environments/production.rb +1 -1
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/config/routes.rb +5 -1
- data/spec/view_helpers_spec.rb +13 -2
- metadata +51 -10
- data/lib/invisible_captcha/validator.rb +0 -15
- data/spec/dummy/script/rails +0 -5
- data/spec/validator_spec.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e100c8a33e03c0cbf7db8c66f9319bf541848f5
|
4
|
+
data.tar.gz: 25593f083c4c23381d6d2cb25988b59fceb29a1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b35f5a39151875efd7f02792c29b253f0e2a9e5136b7c3463959fec74320a055a819fac4a73480e7f88bae788de793e0a7faa2ad77f4f3b80502247a85513db
|
7
|
+
data.tar.gz: 907d391f3a01a0edfaf4926715c35ed981bf06cef8ded02138e60c6e3247f79b11a6ae593bb1e3d5488170a4560870e27d517d2974252d36413f5f26d75d87bf
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Appraisals
ADDED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/invisible_captcha.svg)](http://badge.fury.io/rb/invisible_captcha) [![Build Status](https://travis-ci.org/markets/invisible_captcha.svg)](https://travis-ci.org/markets/invisible_captcha)
|
4
4
|
|
5
|
-
Simple and flexible spam protection solution for Rails applications.
|
5
|
+
> Simple and flexible spam protection solution for Rails applications.
|
6
|
+
|
7
|
+
It is based on the `honeypot` strategy to provide a better user experience. It also provides a time-sensitive form submission.
|
6
8
|
|
7
9
|
**Background**
|
8
10
|
|
9
|
-
The strategy is
|
11
|
+
The strategy is about adding an input field into the form that:
|
10
12
|
|
11
13
|
* shouldn't be visible by the real users
|
12
14
|
* should be left empty by the real users
|
@@ -14,6 +16,8 @@ The strategy is based on adding an input field into the form that:
|
|
14
16
|
|
15
17
|
## Installation
|
16
18
|
|
19
|
+
Invisible Captcha is tested against Rails `>= 3.2` and Ruby `>= 1.9.3`.
|
20
|
+
|
17
21
|
Add this line to you Gemfile:
|
18
22
|
|
19
23
|
```
|
@@ -28,15 +32,13 @@ $ gem install invisible_captcha
|
|
28
32
|
|
29
33
|
## Usage
|
30
34
|
|
31
|
-
There are different ways to implement, at Controller level or Model level:
|
32
|
-
|
33
|
-
### Controller style
|
34
|
-
|
35
35
|
View code:
|
36
36
|
|
37
37
|
```erb
|
38
|
-
<%=
|
39
|
-
<%= invisible_captcha %>
|
38
|
+
<%= form_for(@topic) do |f| %>
|
39
|
+
<%= f.invisible_captcha :subtitle %>
|
40
|
+
<!-- or -->
|
41
|
+
<%= invisible_captcha :subtitle, :topic %>
|
40
42
|
<% end %>
|
41
43
|
```
|
42
44
|
|
@@ -44,67 +46,36 @@ Controller code:
|
|
44
46
|
|
45
47
|
```ruby
|
46
48
|
class TopicsController < ApplicationController
|
47
|
-
invisible_captcha only: [:create, :update]
|
49
|
+
invisible_captcha only: [:create, :update], honeypot: :subtitle
|
48
50
|
end
|
49
51
|
```
|
50
52
|
|
51
|
-
This method will act as a `before_filter` that triggers when spam is detected (honeypot field has some value). By default it responds with no content (only headers: `head(200)`). But you are able to define your own callback by passing a method to the `on_spam` option:
|
53
|
+
This method will act as a `before_filter` that triggers when spam is detected (honeypot field has some value). By default it responds with no content (only headers: `head(200)`). This is a good default, since the bot will surely read the response code and will think that it has achieved to submit the form properly. But, anyway, you are able to define your own callback by passing a method to the `on_spam` option:
|
52
54
|
|
53
55
|
```ruby
|
54
|
-
|
56
|
+
class TopicsController < ApplicationController
|
57
|
+
invisible_captcha only: [:create, :update], on_spam: :your_spam_callback_method
|
55
58
|
|
56
|
-
private
|
59
|
+
private
|
57
60
|
|
58
|
-
def
|
59
|
-
|
61
|
+
def your_spam_callback_method
|
62
|
+
redirect_to root_path
|
63
|
+
end
|
60
64
|
end
|
61
65
|
```
|
62
66
|
|
63
|
-
|
64
|
-
|
65
|
-
### Controller style (resource oriented):
|
66
|
-
|
67
|
-
In your form:
|
68
|
-
|
69
|
-
```erb
|
70
|
-
<%= form_for(@topic) do |f| %>
|
71
|
-
<%= f.invisible_captcha :subtitle %>
|
72
|
-
<!-- or -->
|
73
|
-
<%= invisible_captcha :subtitle, :topic %>
|
74
|
-
<% end %>
|
75
|
-
```
|
76
|
-
|
77
|
-
In your controller:
|
78
|
-
|
79
|
-
```ruby
|
80
|
-
invisible_captcha only: [:create, :update], honeypot: :subtitle
|
81
|
-
```
|
82
|
-
|
83
|
-
### Model style
|
84
|
-
|
85
|
-
View code:
|
67
|
+
Note that isn't mandatory to specify a `honeypot` attribute (nor in the view, nor in the controller). In this case, the engine will take a random field from `InvisibleCaptcha.honeypots`. So, if you're integrating it following this path, in your form:
|
86
68
|
|
87
69
|
```erb
|
88
|
-
<%=
|
89
|
-
<%=
|
70
|
+
<%= form_tag(new_contact_path) do |f| %>
|
71
|
+
<%= invisible_captcha %>
|
90
72
|
<% end %>
|
91
73
|
```
|
92
74
|
|
93
|
-
|
75
|
+
In you controller:
|
94
76
|
|
95
|
-
```ruby
|
96
|
-
class Topic < ActiveRecord::Base
|
97
|
-
attr_accessor :subtitle # define a virtual attribute, the honeypot
|
98
|
-
validates :subtitle, :invisible_captcha => true
|
99
|
-
end
|
100
77
|
```
|
101
|
-
|
102
|
-
If you are using [strong_parameters](https://github.com/rails/strong_parameters) (by default in Rails 4), don't forget to keep the honeypot attribute into the params hash:
|
103
|
-
|
104
|
-
```ruby
|
105
|
-
def topic_params
|
106
|
-
params.require(:topic).permit(:subtitle)
|
107
|
-
end
|
78
|
+
invisible_captcha only: [:new_contact]
|
108
79
|
```
|
109
80
|
|
110
81
|
## Options and customization
|
@@ -115,11 +86,10 @@ This section contains a description of all plugin options and customizations.
|
|
115
86
|
|
116
87
|
You can customize:
|
117
88
|
|
118
|
-
* `sentence_for_humans`: text for real users if input field was visible. By default, it uses I18n (see below)
|
119
|
-
* `
|
120
|
-
* `honeypots`: collection of default honeypots, used by the view helper, called with no args, to generate the honeypot field name
|
89
|
+
* `sentence_for_humans`: text for real users if input field was visible. By default, it uses I18n (see below).
|
90
|
+
* `honeypots`: collection of default honeypots. Used by the view helper, called with no args, to generate a random honeypot field name.
|
121
91
|
* `visual_honeypots`: make honeypots visible, also useful to test/debug your implementation.
|
122
|
-
* `timestamp_threshold`: fastest time (
|
92
|
+
* `timestamp_threshold`: fastest time (in seconds) to expect a human to submit the form (see [original article by Yoav Aner](http://blog.gingerlime.com/2012/simple-detection-of-comment-spam-in-rails/) outlining the idea). By default, 4 seconds. **NOTE:** It's recommended to deactivate the autocomplete feature to avoid false positives (`autocomplete="off"`).
|
123
93
|
* `timestamp_error_message`: flash error message thrown when form submitted quicker than the `timestamp_threshold` value. It uses I18n by default.
|
124
94
|
|
125
95
|
To change these defaults, add the following to an initializer (recommended `config/initializers/invisible_captcha.rb`):
|
@@ -128,9 +98,8 @@ To change these defaults, add the following to an initializer (recommended `conf
|
|
128
98
|
InvisibleCaptcha.setup do |config|
|
129
99
|
config.honeypots += 'fake_resource_title'
|
130
100
|
config.visual_honeypots = false
|
131
|
-
config.timestamp_threshold = 4
|
101
|
+
config.timestamp_threshold = 4
|
132
102
|
# Leave these unset if you want to use I18n (see below)
|
133
|
-
# config.error_message = 'You are a robot!'
|
134
103
|
# config.sentence_for_humans = 'If you are a human, ignore this field'
|
135
104
|
# config.timestamp_error_message = 'Sorry, that was too quick! Please resubmit.'
|
136
105
|
end
|
@@ -145,7 +114,8 @@ The `invisible_captcha` method accepts some options:
|
|
145
114
|
* `honeypot`: name of honeypot.
|
146
115
|
* `scope`: name of scope, ie: 'topic[subtitle]' -> 'topic' is the scope.
|
147
116
|
* `on_spam`: custom callback to be called on spam detection.
|
148
|
-
* `on_timestamp_spam`: custom callback to be called when form submitted too quickly. The default action redirects to `:back` printing a warning in `flash[:error]
|
117
|
+
* `on_timestamp_spam`: custom callback to be called when form submitted too quickly. The default action redirects to `:back` printing a warning in `flash[:error]`.
|
118
|
+
* `timestamp_threshold`: custom threshold per controller/action. Overrides the global value for `InvisibleCaptcha.timestamp_threshold`.
|
149
119
|
|
150
120
|
### View helpers options:
|
151
121
|
|
@@ -167,13 +137,12 @@ Using the view/form helper you can override some defaults for the given instance
|
|
167
137
|
en:
|
168
138
|
invisible_captcha:
|
169
139
|
sentence_for_humans: "If you are human, ignore this field"
|
170
|
-
error_message: "You are a robot!"
|
171
140
|
timestamp_error_message: "Sorry, that was too quick! Please resubmit."
|
172
141
|
```
|
173
142
|
|
174
143
|
You can override the english ones in your own i18n config files as well as add new ones for other locales.
|
175
144
|
|
176
|
-
If you intend to use I18n with `invisible_captcha`, you _must not_ set `sentence_for_humans
|
145
|
+
If you intend to use I18n with `invisible_captcha`, you _must not_ set `sentence_for_humans` or `timestamp_error_message` to strings in the setup phase.
|
177
146
|
|
178
147
|
## Contribute
|
179
148
|
|
@@ -181,20 +150,26 @@ Any kind of idea, feedback or bug report are welcome! Open an [issue](https://gi
|
|
181
150
|
|
182
151
|
## Development
|
183
152
|
|
184
|
-
Clone/fork this repository
|
153
|
+
Clone/fork this repository, start to hack on it and send a pull request.
|
154
|
+
|
155
|
+
Run the test suite:
|
156
|
+
|
157
|
+
```
|
158
|
+
$ bundle exec rspec
|
159
|
+
```
|
185
160
|
|
186
|
-
Run test suite:
|
161
|
+
Run the test suite against all supported versions:
|
187
162
|
|
188
163
|
```
|
189
|
-
$
|
164
|
+
$ bundle exec appraisal rake
|
190
165
|
```
|
191
166
|
|
192
167
|
Start a sample Rails app ([source code](spec/dummy)) with `InvisibleCaptcha` integrated:
|
193
168
|
|
194
169
|
```
|
195
|
-
$ rake web # PORT=4000 (default: 3000)
|
170
|
+
$ bundle exec rake web # PORT=4000 (default: 3000)
|
196
171
|
```
|
197
172
|
|
198
173
|
## License
|
199
174
|
|
200
|
-
Copyright (c) 2012-
|
175
|
+
Copyright (c) 2012-2016 Marc Anguera. Invisible Captcha is released under the [MIT](LICENSE) License.
|
data/invisible_captcha.gemspec
CHANGED
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.version = InvisibleCaptcha::VERSION
|
7
7
|
spec.authors = ["Marc Anguera Insa"]
|
8
8
|
spec.email = ["srmarc.ai@gmail.com"]
|
9
|
-
spec.description =
|
10
|
-
spec.summary =
|
9
|
+
spec.description = "Unobtrusive, flexible and simple spam protection for Rails applications using honeypot strategy for better user experience."
|
10
|
+
spec.summary = "Simple honeypot protection for RoR apps"
|
11
11
|
spec.homepage = "https://github.com/markets/invisible_captcha"
|
12
12
|
spec.license = "MIT"
|
13
13
|
|
@@ -19,5 +19,8 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.add_dependency 'rails'
|
20
20
|
|
21
21
|
spec.add_development_dependency 'rspec-rails', '~> 3.1'
|
22
|
+
spec.add_development_dependency 'appraisal'
|
23
|
+
spec.add_development_dependency 'test-unit', '~> 3.0'
|
24
|
+
spec.add_development_dependency 'mime-types', '< 3.0'
|
22
25
|
end
|
23
26
|
|
data/lib/invisible_captcha.rb
CHANGED
@@ -2,7 +2,6 @@ require 'invisible_captcha/version'
|
|
2
2
|
require 'invisible_captcha/controller_ext'
|
3
3
|
require 'invisible_captcha/view_helpers'
|
4
4
|
require 'invisible_captcha/form_helpers'
|
5
|
-
require 'invisible_captcha/validator'
|
6
5
|
require 'invisible_captcha/railtie'
|
7
6
|
|
8
7
|
module InvisibleCaptcha
|
@@ -25,8 +24,8 @@ module InvisibleCaptcha
|
|
25
24
|
# Default fake fields for controller based workflow
|
26
25
|
self.honeypots = ['foo_id', 'bar_id', 'baz_id']
|
27
26
|
|
28
|
-
# Fastest time to expect a human to submit the form
|
29
|
-
self.timestamp_threshold = 4
|
27
|
+
# Fastest time (in seconds) to expect a human to submit the form
|
28
|
+
self.timestamp_threshold = 4
|
30
29
|
|
31
30
|
# Default error message for validator when form submitted too quickly
|
32
31
|
self.timestamp_error_message = -> { I18n.t('invisible_captcha.timestamp_error_message', default: 'Sorry, that was too quick! Please resubmit.') }
|
@@ -37,16 +37,22 @@ module InvisibleCaptcha
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def invisible_captcha_timestamp?(options = {})
|
40
|
-
timestamp
|
41
|
-
return false unless timestamp.present?
|
40
|
+
timestamp = session[:invisible_captcha_timestamp]
|
42
41
|
|
43
|
-
|
42
|
+
# Consider as spam if timestamp not in session, cause that means the form was not fetched at all
|
43
|
+
unless timestamp
|
44
|
+
logger.warn("Potential spam detected for IP #{request.env['REMOTE_ADDR']}. Invisible Captcha timestamp not found in session.")
|
45
|
+
return true
|
46
|
+
end
|
44
47
|
|
45
|
-
|
46
|
-
return false if time_to_submit >= InvisibleCaptcha.timestamp_threshold
|
48
|
+
time_to_submit = Time.zone.now - DateTime.iso8601(timestamp)
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
+
# Consider as spam if form submitted too quickly
|
51
|
+
if time_to_submit < (options[:timestamp_threshold] || InvisibleCaptcha.timestamp_threshold)
|
52
|
+
logger.warn("Potential spam detected for IP #{request.env['REMOTE_ADDR']}. Invisible Captcha timestamp threshold not reached (took #{time_to_submit.to_i}s).")
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
false
|
50
56
|
end
|
51
57
|
|
52
58
|
def invisible_captcha?(options = {})
|
@@ -10,8 +10,6 @@ module InvisibleCaptcha
|
|
10
10
|
include InvisibleCaptcha::ViewHelpers
|
11
11
|
ActionView::Helpers::FormBuilder.send :include, InvisibleCaptcha::FormHelpers
|
12
12
|
end
|
13
|
-
|
14
|
-
ActiveModel::Validations::InvisibleCaptchaValidator = InvisibleCaptcha::InvisibleCaptchaValidator
|
15
13
|
end
|
16
14
|
end
|
17
|
-
end
|
15
|
+
end
|
data/spec/controllers_spec.rb
CHANGED
@@ -3,7 +3,20 @@ require 'spec_helper'
|
|
3
3
|
describe InvisibleCaptcha::ControllerExt, type: :controller do
|
4
4
|
render_views
|
5
5
|
|
6
|
-
before
|
6
|
+
before do
|
7
|
+
@controller = TopicsController.new
|
8
|
+
InvisibleCaptcha.timestamp_threshold = 1
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'without invisible_captcha_timestamp in session' do
|
12
|
+
it 'fails like if it was submitted too fast' do
|
13
|
+
request.env['HTTP_REFERER'] = 'http://test.host/topics'
|
14
|
+
post :create, topic: { title: 'foo' }
|
15
|
+
|
16
|
+
expect(response).to redirect_to :back
|
17
|
+
expect(flash[:error]).to eq(InvisibleCaptcha.timestamp_error_message)
|
18
|
+
end
|
19
|
+
end
|
7
20
|
|
8
21
|
context 'submission timestamp_threshold' do
|
9
22
|
before do
|
@@ -12,47 +25,53 @@ describe InvisibleCaptcha::ControllerExt, type: :controller do
|
|
12
25
|
|
13
26
|
it 'fails if submission before timestamp_threshold' do
|
14
27
|
request.env['HTTP_REFERER'] = 'http://test.host/topics'
|
15
|
-
post :create,
|
28
|
+
post :create, topic: { title: 'foo' }
|
16
29
|
|
17
|
-
expect(flash[:error]).to eq(InvisibleCaptcha.timestamp_error_message)
|
18
30
|
expect(response).to redirect_to :back
|
31
|
+
expect(flash[:error]).to eq(InvisibleCaptcha.timestamp_error_message)
|
19
32
|
end
|
20
33
|
|
21
|
-
it 'allow custom on_timestamp_spam callback'
|
22
|
-
put :update,
|
34
|
+
it 'allow custom on_timestamp_spam callback' do
|
35
|
+
put :update, id: 1, topic: { title: 'bar' }
|
23
36
|
|
24
37
|
expect(response).to redirect_to(root_path)
|
25
38
|
end
|
26
39
|
|
27
40
|
context 'successful submissions' do
|
28
|
-
|
29
|
-
# Wait for valid submission
|
41
|
+
it 'passes if submission on or after timestamp_threshold' do
|
30
42
|
sleep InvisibleCaptcha.timestamp_threshold
|
31
|
-
end
|
32
43
|
|
33
|
-
it 'passes if submission on or after timestamp_threshold' do
|
34
44
|
post :create, topic: { title: 'foo' }
|
35
45
|
|
36
46
|
expect(flash[:error]).not_to be_present
|
37
47
|
expect(response.body).to be_present
|
38
48
|
end
|
49
|
+
|
50
|
+
it 'allow to set a custom timestamp_threshold per action' do
|
51
|
+
sleep 2 # custom threshold
|
52
|
+
|
53
|
+
post :publish, id: 1
|
54
|
+
|
55
|
+
expect(flash[:error]).not_to be_present
|
56
|
+
expect(response.body).to be_present
|
57
|
+
end
|
39
58
|
end
|
40
59
|
end
|
41
60
|
|
42
|
-
context '
|
61
|
+
context 'honeypot attribute' do
|
43
62
|
before do
|
44
63
|
session[:invisible_captcha_timestamp] = Time.zone.now.iso8601
|
45
64
|
# Wait for valid submission
|
46
65
|
sleep InvisibleCaptcha.timestamp_threshold
|
47
66
|
end
|
48
67
|
|
49
|
-
it 'with spam' do
|
68
|
+
it 'fails with spam' do
|
50
69
|
post :create, topic: { subtitle: 'foo' }
|
51
70
|
|
52
71
|
expect(response.body).to be_blank
|
53
72
|
end
|
54
73
|
|
55
|
-
it 'with no spam' do
|
74
|
+
it 'passes with no spam' do
|
56
75
|
post :create, topic: { title: 'foo' }
|
57
76
|
|
58
77
|
expect(response.body).to be_present
|
@@ -3,6 +3,7 @@ class TopicsController < ApplicationController
|
|
3
3
|
invisible_captcha honeypot: :subtitle, only: :update,
|
4
4
|
on_spam: :custom_callback,
|
5
5
|
on_timestamp_spam: :custom_timestamp_callback
|
6
|
+
invisible_captcha honeypot: :subtitle, only: :publish, timestamp_threshold: 2
|
6
7
|
|
7
8
|
def new
|
8
9
|
@topic = Topic.new
|
@@ -21,6 +22,10 @@ class TopicsController < ApplicationController
|
|
21
22
|
def update
|
22
23
|
end
|
23
24
|
|
25
|
+
def publish
|
26
|
+
redirect_to new_topic_path
|
27
|
+
end
|
28
|
+
|
24
29
|
private
|
25
30
|
|
26
31
|
def custom_callback
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/view_helpers_spec.rb
CHANGED
@@ -11,12 +11,23 @@ describe InvisibleCaptcha::ViewHelpers, type: :helper do
|
|
11
11
|
else
|
12
12
|
InvisibleCaptcha.visual_honeypots
|
13
13
|
end
|
14
|
+
style_attributes, input_attributes = if Gem::Version.new(Rails.version) > Gem::Version.new("4.2.0")
|
15
|
+
[
|
16
|
+
'type="text/css" media="screen" scoped="scoped"',
|
17
|
+
"type=\"text\" name=\"#{input_name}\" id=\"#{input_id}\""
|
18
|
+
]
|
19
|
+
else
|
20
|
+
[
|
21
|
+
'media="screen" scoped="scoped" type="text/css"',
|
22
|
+
"id=\"#{input_id}\" name=\"#{input_name}\" type=\"text\""
|
23
|
+
]
|
24
|
+
end
|
14
25
|
|
15
26
|
%{
|
16
27
|
<div id="#{html_id}">
|
17
|
-
<style
|
28
|
+
<style #{style_attributes}>#{visibilty ? '' : "##{html_id} { display:none; }"}</style>
|
18
29
|
<label for="#{input_id}">#{InvisibleCaptcha.sentence_for_humans}</label>
|
19
|
-
<input
|
30
|
+
<input #{input_attributes} />
|
20
31
|
</div>
|
21
32
|
}.gsub(/\s+/, ' ').strip.gsub('> <', '><')
|
22
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: invisible_captcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc Anguera Insa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -38,8 +38,50 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.1'
|
41
|
-
|
42
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: appraisal
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: test-unit
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mime-types
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "<"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
description: Unobtrusive, flexible and simple spam protection for Rails applications
|
84
|
+
using honeypot strategy for better user experience.
|
43
85
|
email:
|
44
86
|
- srmarc.ai@gmail.com
|
45
87
|
executables: []
|
@@ -49,16 +91,19 @@ files:
|
|
49
91
|
- ".gitignore"
|
50
92
|
- ".rspec"
|
51
93
|
- ".travis.yml"
|
94
|
+
- Appraisals
|
52
95
|
- Gemfile
|
53
96
|
- LICENSE
|
54
97
|
- README.md
|
55
98
|
- Rakefile
|
99
|
+
- gemfiles/rails_3.2.gemfile
|
100
|
+
- gemfiles/rails_4.1.gemfile
|
101
|
+
- gemfiles/rails_4.2.gemfile
|
56
102
|
- invisible_captcha.gemspec
|
57
103
|
- lib/invisible_captcha.rb
|
58
104
|
- lib/invisible_captcha/controller_ext.rb
|
59
105
|
- lib/invisible_captcha/form_helpers.rb
|
60
106
|
- lib/invisible_captcha/railtie.rb
|
61
|
-
- lib/invisible_captcha/validator.rb
|
62
107
|
- lib/invisible_captcha/version.rb
|
63
108
|
- lib/invisible_captcha/view_helpers.rb
|
64
109
|
- spec/controllers_spec.rb
|
@@ -104,10 +149,8 @@ files:
|
|
104
149
|
- spec/dummy/public/422.html
|
105
150
|
- spec/dummy/public/500.html
|
106
151
|
- spec/dummy/public/favicon.ico
|
107
|
-
- spec/dummy/script/rails
|
108
152
|
- spec/invisible_captcha_spec.rb
|
109
153
|
- spec/spec_helper.rb
|
110
|
-
- spec/validator_spec.rb
|
111
154
|
- spec/view_helpers_spec.rb
|
112
155
|
homepage: https://github.com/markets/invisible_captcha
|
113
156
|
licenses:
|
@@ -129,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
172
|
version: '0'
|
130
173
|
requirements: []
|
131
174
|
rubyforge_project:
|
132
|
-
rubygems_version: 2.
|
175
|
+
rubygems_version: 2.4.5
|
133
176
|
signing_key:
|
134
177
|
specification_version: 4
|
135
178
|
summary: Simple honeypot protection for RoR apps
|
@@ -177,8 +220,6 @@ test_files:
|
|
177
220
|
- spec/dummy/public/422.html
|
178
221
|
- spec/dummy/public/500.html
|
179
222
|
- spec/dummy/public/favicon.ico
|
180
|
-
- spec/dummy/script/rails
|
181
223
|
- spec/invisible_captcha_spec.rb
|
182
224
|
- spec/spec_helper.rb
|
183
|
-
- spec/validator_spec.rb
|
184
225
|
- spec/view_helpers_spec.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module InvisibleCaptcha
|
2
|
-
class InvisibleCaptchaValidator < ActiveModel::EachValidator
|
3
|
-
def validate_each(record, attribute, value)
|
4
|
-
if invisible_captcha?(record, attribute)
|
5
|
-
record.errors[:base] = InvisibleCaptcha.error_message
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
def invisible_captcha?(object, honeypot)
|
12
|
-
object.send(honeypot).present?
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
data/spec/dummy/script/rails
DELETED
data/spec/validator_spec.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe InvisibleCaptcha::InvisibleCaptchaValidator do
|
4
|
-
it 'do not pass validations if honeypot is presented' do
|
5
|
-
topic = Topic.new(title: 'foo')
|
6
|
-
expect(topic.valid?).to be true
|
7
|
-
|
8
|
-
topic.subtitle = 'foo'
|
9
|
-
expect(topic.valid?).to be false
|
10
|
-
expect(topic.errors.messages[:base]).to eq [InvisibleCaptcha.error_message]
|
11
|
-
end
|
12
|
-
end
|