invisible_captcha 0.7.0 → 0.8.0
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/LICENSE +1 -1
- data/README.md +26 -14
- data/lib/invisible_captcha/form_helpers.rb +2 -2
- data/lib/invisible_captcha/railtie.rb +13 -5
- data/lib/invisible_captcha/validator.rb +0 -3
- data/lib/invisible_captcha/version.rb +1 -1
- data/lib/invisible_captcha/view_helpers.rb +21 -10
- data/spec/dummy/app/controllers/topics_controller.rb +1 -1
- data/spec/dummy/app/models/topic.rb +1 -0
- data/spec/dummy/app/views/layouts/application.html.erb +11 -0
- data/spec/dummy/app/views/topics/new.html.erb +20 -1
- data/spec/validator_spec.rb +1 -1
- data/spec/view_helpers_spec.rb +63 -0
- metadata +4 -4
- data/spec/helpers_spec.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03aab9758bfbaf12adb3913f5b37c8423d269c2e
|
4
|
+
data.tar.gz: 18e136fc292c192126f7c08d5d60286a4c86ba6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c60cc1997f5748fef444f1eea60aa3a47b42ee6de60dffa8f320e346608e224594f4252efbe19d7df80edaf8c137729df4357162cb27f2e8b6c7fa1327aed94f
|
7
|
+
data.tar.gz: b5b62112cf6ea24aab60e66f589a0756d06e7337c7564e43cdea6a838023334c43e22cba5e486c3c8b1278fe1ef4829a5c925fea3e4917ba919677bd10710049
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -109,26 +109,16 @@ end
|
|
109
109
|
|
110
110
|
## Options and customization
|
111
111
|
|
112
|
-
This section contains
|
113
|
-
|
114
|
-
### Controller method options:
|
115
|
-
|
116
|
-
The `invisible_captcha` method accepts some options:
|
117
|
-
|
118
|
-
* `only`: apply to given controller actions.
|
119
|
-
* `except`: exclude to given controller actions.
|
120
|
-
* `honeypot`: name of honeypot.
|
121
|
-
* `scope`: name of scope, ie: 'topic[subtitle]' -> 'topic' is the scope.
|
122
|
-
* `on_spam`: custom callback to be called on spam detection.
|
112
|
+
This section contains a description of all plugin options and customizations.
|
123
113
|
|
124
114
|
### Plugin options:
|
125
115
|
|
126
|
-
You
|
116
|
+
You can customize:
|
127
117
|
|
128
118
|
* `sentence_for_humans`: text for real users if input field was visible.
|
129
119
|
* `error_message`: error message thrown by model validation (only model implementation).
|
130
120
|
* `honeypots`: collection of default honeypots, used by the view helper, called with no args, to generate the honeypot field name
|
131
|
-
* `visual_honeypots`: make honeypots visible, useful to test/debug your implementation.
|
121
|
+
* `visual_honeypots`: make honeypots visible, also useful to test/debug your implementation.
|
132
122
|
|
133
123
|
To change these defaults, add the following to an initializer (recommended `config/initializers/invisible_captcha.rb`):
|
134
124
|
|
@@ -141,6 +131,28 @@ InvisibleCaptcha.setup do |config|
|
|
141
131
|
end
|
142
132
|
```
|
143
133
|
|
134
|
+
### Controller method options:
|
135
|
+
|
136
|
+
The `invisible_captcha` method accepts some options:
|
137
|
+
|
138
|
+
* `only`: apply to given controller actions.
|
139
|
+
* `except`: exclude to given controller actions.
|
140
|
+
* `honeypot`: name of honeypot.
|
141
|
+
* `scope`: name of scope, ie: 'topic[subtitle]' -> 'topic' is the scope.
|
142
|
+
* `on_spam`: custom callback to be called on spam detection.
|
143
|
+
|
144
|
+
### View helpers options:
|
145
|
+
|
146
|
+
Using the view/form helper you can override some defaults for the given instance. Actually, it allows to change: `sentence_for_humans` and `visual_honeypots`.
|
147
|
+
|
148
|
+
```erb
|
149
|
+
<%= form_for(@topic) do |f| %>
|
150
|
+
<%= f.invisible_captcha :subtitle, visual_honeypots: true, sentence_for_humans: "Ei, don't fill on this input!" %>
|
151
|
+
<!-- or -->
|
152
|
+
<%= invisible_captcha visual_honeypots: true, sentence_for_humans: "Ei, don't fill on this input!" %>
|
153
|
+
<% end %>
|
154
|
+
```
|
155
|
+
|
144
156
|
## Contribute
|
145
157
|
|
146
158
|
Any kind of idea, feedback or bug report are welcome! Open an [issue](https://github.com/markets/invisible_captcha/issues) or send a [pull request](https://github.com/markets/invisible_captcha/pulls).
|
@@ -163,4 +175,4 @@ $ rake web # PORT=4000 (default: 3000)
|
|
163
175
|
|
164
176
|
## License
|
165
177
|
|
166
|
-
Copyright (c) 2012-
|
178
|
+
Copyright (c) 2012-2015 Marc Anguera. Invisible Captcha is released under the [MIT](LICENSE) License.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module InvisibleCaptcha
|
2
2
|
module FormHelpers
|
3
|
-
def invisible_captcha(honeypot)
|
4
|
-
@template.invisible_captcha(honeypot, self.object_name)
|
3
|
+
def invisible_captcha(honeypot, options = {})
|
4
|
+
@template.invisible_captcha(honeypot, self.object_name, options)
|
5
5
|
end
|
6
6
|
end
|
7
7
|
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
module InvisibleCaptcha
|
2
2
|
class Railtie < Rails::Railtie
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
initializer 'invisible_captcha.rails_integration' do
|
4
|
+
ActiveSupport.on_load(:action_controller) do
|
5
|
+
include InvisibleCaptcha::ControllerExt
|
6
|
+
extend InvisibleCaptcha::ControllerExt::ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
ActiveSupport.on_load(:action_view) do
|
10
|
+
include InvisibleCaptcha::ViewHelpers
|
11
|
+
ActionView::Helpers::FormBuilder.send :include, InvisibleCaptcha::FormHelpers
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveModel::Validations::InvisibleCaptchaValidator = InvisibleCaptcha::InvisibleCaptchaValidator
|
15
|
+
end
|
8
16
|
end
|
9
17
|
end
|
@@ -1,10 +1,7 @@
|
|
1
|
-
require 'active_model/validator'
|
2
|
-
|
3
1
|
module InvisibleCaptcha
|
4
2
|
class InvisibleCaptchaValidator < ActiveModel::EachValidator
|
5
3
|
def validate_each(record, attribute, value)
|
6
4
|
if invisible_captcha?(record, attribute)
|
7
|
-
record.errors.clear
|
8
5
|
record.errors[:base] = InvisibleCaptcha.error_message
|
9
6
|
end
|
10
7
|
end
|
@@ -5,31 +5,42 @@ module InvisibleCaptcha
|
|
5
5
|
# @param honeypot [Symbol] name of honeypot, ie: subtitle => input name: subtitle
|
6
6
|
# @param scope [Symbol] name of honeypot scope, ie: topic => input name: topic[subtitle]
|
7
7
|
# @return [String] the generated html
|
8
|
-
def invisible_captcha(honeypot = nil, scope = nil)
|
9
|
-
build_invisible_captcha(honeypot, scope)
|
8
|
+
def invisible_captcha(honeypot = nil, scope = nil, options = {})
|
9
|
+
build_invisible_captcha(honeypot, scope, options)
|
10
10
|
end
|
11
11
|
|
12
12
|
private
|
13
13
|
|
14
|
-
def build_invisible_captcha(honeypot = nil, scope = nil)
|
14
|
+
def build_invisible_captcha(honeypot = nil, scope = nil, options = {})
|
15
|
+
if honeypot.is_a?(Hash)
|
16
|
+
options = honeypot
|
17
|
+
honeypot = nil
|
18
|
+
end
|
19
|
+
|
15
20
|
honeypot = honeypot ? honeypot.to_s : InvisibleCaptcha.get_honeypot
|
16
|
-
label = InvisibleCaptcha.sentence_for_humans
|
21
|
+
label = options[:sentence_for_humans] || InvisibleCaptcha.sentence_for_humans
|
17
22
|
html_id = generate_html_id(honeypot, scope)
|
18
23
|
|
19
24
|
content_tag(:div, :id => html_id) do
|
20
|
-
|
21
|
-
label_tag(build_label_name(honeypot, scope), label)
|
22
|
-
text_field_tag(build_text_field_name(honeypot, scope))
|
23
|
-
end
|
25
|
+
concat visibility_css(html_id, options)
|
26
|
+
concat label_tag(build_label_name(honeypot, scope), label)
|
27
|
+
concat text_field_tag(build_text_field_name(honeypot, scope))
|
28
|
+
end
|
24
29
|
end
|
25
30
|
|
26
31
|
def generate_html_id(honeypot, scope = nil)
|
27
32
|
"#{scope || honeypot}_#{Time.now.to_i}"
|
28
33
|
end
|
29
34
|
|
30
|
-
def
|
35
|
+
def visibility_css(container_id, options)
|
36
|
+
visibility = if options.key?(:visual_honeypots)
|
37
|
+
options[:visual_honeypots]
|
38
|
+
else
|
39
|
+
InvisibleCaptcha.visual_honeypots
|
40
|
+
end
|
41
|
+
|
31
42
|
content_tag(:style, :type => 'text/css', :media => 'screen', :scoped => 'scoped') do
|
32
|
-
|
43
|
+
"##{container_id} { display:none; }" unless visibility
|
33
44
|
end
|
34
45
|
end
|
35
46
|
|
@@ -8,6 +8,17 @@
|
|
8
8
|
</head>
|
9
9
|
<body>
|
10
10
|
|
11
|
+
<%= link_to "Default", new_topic_path %> |
|
12
|
+
<%= link_to "With visual honeypots", new_topic_path(context: "visual_honeypots") %>
|
13
|
+
|
14
|
+
<% flash.each do |key, value| %>
|
15
|
+
<ul>
|
16
|
+
<li>
|
17
|
+
<%= "[#{key.upcase}] #{value}" %>
|
18
|
+
</li>
|
19
|
+
</ul>
|
20
|
+
<% end %>
|
21
|
+
|
11
22
|
<%= yield %>
|
12
23
|
|
13
24
|
</body>
|
@@ -1,16 +1,35 @@
|
|
1
1
|
<h1>New topic</h1>
|
2
2
|
|
3
|
+
<% if @topic.errors.any? %>
|
4
|
+
<div>
|
5
|
+
<h2><%= pluralize(@topic.errors.count, "error") %> prohibited this record from being saved:</h2>
|
6
|
+
<ul>
|
7
|
+
<% @topic.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
3
14
|
<%= form_for(@topic) do |f| %>
|
4
|
-
<%=
|
15
|
+
<%= hidden_field_tag :context, params[:context] %>
|
16
|
+
|
17
|
+
<% if params[:context].blank? || params[:context] == 'default' %>
|
18
|
+
<%= f.invisible_captcha :subtitle %>
|
19
|
+
<% else %>
|
20
|
+
<%= f.invisible_captcha :subtitle, visual_honeypots: true %>
|
21
|
+
<% end %>
|
5
22
|
|
6
23
|
<div class="field">
|
7
24
|
<%= f.label :title %><br />
|
8
25
|
<%= f.text_field :title %>
|
9
26
|
</div>
|
27
|
+
|
10
28
|
<div class="field">
|
11
29
|
<%= f.label :body %><br />
|
12
30
|
<%= f.text_area :body %>
|
13
31
|
</div>
|
32
|
+
|
14
33
|
<div class="actions">
|
15
34
|
<%= f.submit %>
|
16
35
|
</div>
|
data/spec/validator_spec.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe InvisibleCaptcha::ViewHelpers, type: :helper do
|
4
|
+
def helper_output(honeypot = nil, scope = nil, options = {})
|
5
|
+
honeypot ||= InvisibleCaptcha.get_honeypot
|
6
|
+
input_id = build_label_name(honeypot, scope)
|
7
|
+
input_name = build_text_field_name(honeypot, scope)
|
8
|
+
html_id = generate_html_id(honeypot, scope)
|
9
|
+
visibilty = if options.key?(:visual_honeypots)
|
10
|
+
options[:visual_honeypots]
|
11
|
+
else
|
12
|
+
InvisibleCaptcha.visual_honeypots
|
13
|
+
end
|
14
|
+
|
15
|
+
%{
|
16
|
+
<div id="#{html_id}">
|
17
|
+
<style type="text/css" media="screen" scoped="scoped">#{visibilty ? '' : "##{html_id} { display:none; }"}</style>
|
18
|
+
<label for="#{input_id}">#{InvisibleCaptcha.sentence_for_humans}</label>
|
19
|
+
<input type="text" name="#{input_name}" id="#{input_id}" />
|
20
|
+
</div>
|
21
|
+
}.gsub(/\s+/, ' ').strip.gsub('> <', '><')
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
allow(Time).to receive(:now).and_return(Time.parse('Feb 19 1986'))
|
26
|
+
InvisibleCaptcha.visual_honeypots = false
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'with no arguments' do
|
30
|
+
InvisibleCaptcha.honeypots = [:foo_id]
|
31
|
+
expect(invisible_captcha).to eq(helper_output)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'with specific honeypot' do
|
35
|
+
expect(invisible_captcha(:subtitle)).to eq(helper_output(:subtitle))
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'with specific honeypot and scope' do
|
39
|
+
expect(invisible_captcha(:subtitle, :topic)).to eq(helper_output(:subtitle, :topic))
|
40
|
+
end
|
41
|
+
|
42
|
+
context "honeypot visibilty" do
|
43
|
+
it 'visible from defaults' do
|
44
|
+
InvisibleCaptcha.honeypots = [:foo_id]
|
45
|
+
InvisibleCaptcha.visual_honeypots = true
|
46
|
+
|
47
|
+
expect(invisible_captcha).to eq(helper_output)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'visible from given instance (default override)' do
|
51
|
+
InvisibleCaptcha.honeypots = [:foo_id]
|
52
|
+
|
53
|
+
expect(invisible_captcha(visual_honeypots: true)).to eq(helper_output(nil, nil, visual_honeypots: true))
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'invisible from given instance (default override)' do
|
57
|
+
InvisibleCaptcha.honeypots = [:foo_id]
|
58
|
+
InvisibleCaptcha.visual_honeypots = true
|
59
|
+
|
60
|
+
expect(invisible_captcha(visual_honeypots: false)).to eq(helper_output(nil, nil, visual_honeypots: false))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
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.8.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:
|
11
|
+
date: 2015-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -96,10 +96,10 @@ files:
|
|
96
96
|
- spec/dummy/public/500.html
|
97
97
|
- spec/dummy/public/favicon.ico
|
98
98
|
- spec/dummy/script/rails
|
99
|
-
- spec/helpers_spec.rb
|
100
99
|
- spec/invisible_captcha_spec.rb
|
101
100
|
- spec/spec_helper.rb
|
102
101
|
- spec/validator_spec.rb
|
102
|
+
- spec/view_helpers_spec.rb
|
103
103
|
homepage: https://github.com/markets/invisible_captcha
|
104
104
|
licenses:
|
105
105
|
- MIT
|
@@ -161,7 +161,7 @@ test_files:
|
|
161
161
|
- spec/dummy/public/500.html
|
162
162
|
- spec/dummy/public/favicon.ico
|
163
163
|
- spec/dummy/script/rails
|
164
|
-
- spec/helpers_spec.rb
|
165
164
|
- spec/invisible_captcha_spec.rb
|
166
165
|
- spec/spec_helper.rb
|
167
166
|
- spec/validator_spec.rb
|
167
|
+
- spec/view_helpers_spec.rb
|
data/spec/helpers_spec.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe InvisibleCaptcha::ViewHelpers, type: :helper do
|
4
|
-
def helper_output(honeypot = nil, scope = nil)
|
5
|
-
honeypot ||= InvisibleCaptcha.get_honeypot
|
6
|
-
input_id = build_label_name(honeypot, scope)
|
7
|
-
input_name = build_text_field_name(honeypot, scope)
|
8
|
-
html_id = generate_html_id(honeypot, scope)
|
9
|
-
|
10
|
-
%{
|
11
|
-
<div id="#{html_id}">
|
12
|
-
<style media="screen" scoped="scoped" type="text/css">#{InvisibleCaptcha.visual_honeypots ? '' : "##{html_id} { display:none; }"}</style>
|
13
|
-
<label for="#{input_id}">#{InvisibleCaptcha.sentence_for_humans}</label>
|
14
|
-
<input id="#{input_id}" name="#{input_name}" type="text" />
|
15
|
-
</div>
|
16
|
-
}.gsub(/\s+/, ' ').strip.gsub('> <', '><')
|
17
|
-
end
|
18
|
-
|
19
|
-
before do
|
20
|
-
allow(Time).to receive(:now).and_return(Time.parse('Feb 19 1986'))
|
21
|
-
InvisibleCaptcha.visual_honeypots = false
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'view helper with no arguments' do
|
25
|
-
InvisibleCaptcha.honeypots = [:foo_id]
|
26
|
-
expect(invisible_captcha).to eq(helper_output)
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'view helper with specific honeypot' do
|
30
|
-
expect(invisible_captcha(:subtitle)).to eq(helper_output(:subtitle))
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'view helper with specific honeypot and scope' do
|
34
|
-
expect(invisible_captcha(:subtitle, :topic)).to eq(helper_output(:subtitle, :topic))
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'view helper with visual honeypots enabled' do
|
38
|
-
InvisibleCaptcha.honeypots = [:foo_id]
|
39
|
-
InvisibleCaptcha.visual_honeypots = true
|
40
|
-
|
41
|
-
expect(invisible_captcha).to eq(helper_output)
|
42
|
-
end
|
43
|
-
end
|