karsthammer-validates_captcha 0.9.5a
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +22 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +320 -0
- data/Rakefile +102 -0
- data/lib/validates_captcha.rb +76 -0
- data/lib/validates_captcha/controller_validation.rb +63 -0
- data/lib/validates_captcha/form_builder.rb +16 -0
- data/lib/validates_captcha/form_helper.rb +39 -0
- data/lib/validates_captcha/image_generator/simple.rb +94 -0
- data/lib/validates_captcha/model_validation.rb +65 -0
- data/lib/validates_captcha/provider/dynamic_image.rb +240 -0
- data/lib/validates_captcha/provider/question.rb +110 -0
- data/lib/validates_captcha/provider/static_image.rb +224 -0
- data/lib/validates_captcha/string_generator/simple.rb +81 -0
- data/lib/validates_captcha/symmetric_encryptor/simple.rb +52 -0
- data/lib/validates_captcha/test_case.rb +12 -0
- data/lib/validates_captcha/version.rb +9 -0
- data/rails/init.rb +29 -0
- data/tasks/static_image_tasks.rake +33 -0
- data/test/cases/controller_validation_test.rb +222 -0
- data/test/cases/image_generator/simple_test.rb +34 -0
- data/test/cases/model_validation_test.rb +258 -0
- data/test/cases/provider/dynamic_image_test.rb +103 -0
- data/test/cases/provider/question_test.rb +41 -0
- data/test/cases/provider/static_image_test.rb +148 -0
- data/test/cases/string_generator/simple_test.rb +115 -0
- data/test/cases/symmetric_encryptor/simple_test.rb +28 -0
- data/test/cases/validates_captcha_test.rb +28 -0
- data/test/test_helper.rb +26 -0
- metadata +120 -0
data/CHANGELOG.rdoc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
== 0.9.5 (October 9, 2009)
|
2
|
+
|
3
|
+
* API change: renamed Provider::Image to Provider::DynamicImage in order to guard against confusion
|
4
|
+
|
5
|
+
* API change: renamed ReversibleEncrypter to SymmetricEncryptor
|
6
|
+
|
7
|
+
* ReversibleEncrypter::Simple class now uses ActiveSupport's MessageEncryptor instead of custom implementation
|
8
|
+
|
9
|
+
|
10
|
+
== 0.9.4 (October 7, 2009)
|
11
|
+
|
12
|
+
* Include new StaticImage provider
|
13
|
+
|
14
|
+
|
15
|
+
== 0.9.3 (September 29, 2009)
|
16
|
+
|
17
|
+
* Change API, include new Question provider, make it the default one
|
18
|
+
|
19
|
+
|
20
|
+
== 0.9.2 (September 27, 2009)
|
21
|
+
|
22
|
+
* Initial version
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2009 Martin Andert
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,320 @@
|
|
1
|
+
= Validates Captcha
|
2
|
+
|
3
|
+
A captcha verification approach for Rails apps, directly integrated into
|
4
|
+
ActiveRecord's validation mechanism and providing helpers for ActionController
|
5
|
+
and ActionView.
|
6
|
+
|
7
|
+
RDoc documentation (including this README as start page) can be found at
|
8
|
+
http://m4n.github.com/validates_captcha. Validates Captcha was first
|
9
|
+
announced {here}[http://m4n.github.com/2009/09/28/introducing-validates-captcha.html].
|
10
|
+
|
11
|
+
By default, question/answer captcha challenges are used, but you can also switch
|
12
|
+
to the built-in image captcha providers. If you stick to ValidatesCaptcha’s API,
|
13
|
+
you can even implement your own captcha challenge provider.
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
== Basic Usage
|
18
|
+
|
19
|
+
Validates Captcha extends ActiveRecord, ActionController and ActionView with
|
20
|
+
helper methods that make it a snap to integrate captcha verification in your
|
21
|
+
Rails application.
|
22
|
+
|
23
|
+
<b>Step #1:</b> Extend your view’s form with the necessary captcha display and
|
24
|
+
input logic.
|
25
|
+
|
26
|
+
# app/views/comments/new.html.erb
|
27
|
+
<% form_for @comment do |f| %>
|
28
|
+
<%= f.error_messages %>
|
29
|
+
|
30
|
+
<!-- standard input fields: -->
|
31
|
+
<p>
|
32
|
+
<%= f.label :name %><br />
|
33
|
+
<%= f.text_field :name %>
|
34
|
+
</p>
|
35
|
+
<!-- ... -->
|
36
|
+
|
37
|
+
<!-- now something new: -->
|
38
|
+
<p>
|
39
|
+
<%= f.label :captcha %><br />
|
40
|
+
<%= f.captcha_challenge # displays the question or image %>
|
41
|
+
<%= f.captcha_field # displays the input field %>
|
42
|
+
</p>
|
43
|
+
|
44
|
+
<p>
|
45
|
+
<%= f.submit 'Create' %>
|
46
|
+
</p>
|
47
|
+
<% end %>
|
48
|
+
|
49
|
+
<b>Step #2:</b> Tell the controller that you want to validate
|
50
|
+
captchas.
|
51
|
+
|
52
|
+
class CommentsController < ApplicationController
|
53
|
+
validates_captcha
|
54
|
+
|
55
|
+
def create
|
56
|
+
# scaffold comment creation code ...
|
57
|
+
end
|
58
|
+
|
59
|
+
# more actions here ...
|
60
|
+
end
|
61
|
+
|
62
|
+
This activates captcha validation in every action of the controller
|
63
|
+
whenever an instance of class +Comment+ is saved.
|
64
|
+
|
65
|
+
<b>Step #3:</b> There's no step three!
|
66
|
+
|
67
|
+
To summarize: Put the following in your view.
|
68
|
+
|
69
|
+
<%= f.captcha_challenge %>
|
70
|
+
<%= f.captcha_field %>
|
71
|
+
|
72
|
+
And what you see below in the corresponding controller.
|
73
|
+
|
74
|
+
validates_captcha
|
75
|
+
|
76
|
+
Done.
|
77
|
+
|
78
|
+
== Customization
|
79
|
+
|
80
|
+
Because the +validates_captcha+ controller method internally creates an
|
81
|
+
around filter, you can (de)activate captcha validation for specific actions.
|
82
|
+
|
83
|
+
validates_captcha :only => [:create, :update]
|
84
|
+
validates_captcha :except => :reset
|
85
|
+
|
86
|
+
The class for which captcha validation is activated is derived from
|
87
|
+
the name of the controller. So putting +validates_captcha+ in a
|
88
|
+
+UsersController+ validates instances of the +User+ class.
|
89
|
+
|
90
|
+
You can customize the validated class using the +validates_captcha_of+ method.
|
91
|
+
|
92
|
+
class ArticlesController < ApplicationController
|
93
|
+
validates_captcha_of Post
|
94
|
+
validates_captcha_of :blog_entries, :except => :persist
|
95
|
+
validates_captcha_of 'users', :only => :store
|
96
|
+
end
|
97
|
+
|
98
|
+
Two kinds of errors are added to the model if captcha validation fails:
|
99
|
+
+:blank+ if no captcha solution is submitted and +:invalid+ if a captcha
|
100
|
+
solution is submitted but does not solve the captcha's challenge. You can
|
101
|
+
localize the error messages for the captcha as you usually do for the
|
102
|
+
other attributes.
|
103
|
+
|
104
|
+
models:
|
105
|
+
comment:
|
106
|
+
attributes:
|
107
|
+
captcha_solution:
|
108
|
+
blank: 'must not be empty'
|
109
|
+
invalid: 'does not match the code displayed on the image'
|
110
|
+
|
111
|
+
What if the image captcha's text is unreadable or a user does not know the
|
112
|
+
correct answer to the captcha question? There's also a form helper method
|
113
|
+
for captcha regeneration available. You can call it like this.
|
114
|
+
|
115
|
+
<p>
|
116
|
+
Don't know the answer? <%= f.regenerate_captcha_challenge_link %>
|
117
|
+
</p>
|
118
|
+
|
119
|
+
This generates an anchor tag that, when clicked, generates a new captcha
|
120
|
+
challenge and updates the display. It makes an AJAX request to fetch a
|
121
|
+
new challenge and updates the question/image after the request is complete.
|
122
|
+
|
123
|
+
+regenerate_captcha_challenge_link+ internally calls Rails' +link_to_remote+
|
124
|
+
helper method. So it relies on the Prototype javascript framework to be
|
125
|
+
available on the page.
|
126
|
+
|
127
|
+
The anchor's text defaults to 'New question' (question challenge) and
|
128
|
+
'Regenerate Captcha' (image challenge) respectively. You can set this to
|
129
|
+
a custom value by providing a +:text+ key in the options hash.
|
130
|
+
|
131
|
+
<%= f.regenerate_captcha_challenge_link :text => 'Another captcha, please' %>
|
132
|
+
|
133
|
+
Apart from controllers, you can activate captcha validation for a model
|
134
|
+
using the class level +with_captcha_validation+ method added to
|
135
|
+
ActiveRecord::Base.
|
136
|
+
|
137
|
+
Comment.with_captcha_validation do
|
138
|
+
@comment = Comment.new(...)
|
139
|
+
@comment.save
|
140
|
+
end
|
141
|
+
|
142
|
+
This activates captcha validation on entering the block and deactivates it
|
143
|
+
on leaving the block.
|
144
|
+
|
145
|
+
Two new attribute-like methods are added to ActiveRecord: +captcha_challenge+
|
146
|
+
and +captcha_solution+. Those are made +attr_accessible+. The former is
|
147
|
+
initialized to a randomly generated captcha challenge on instantiation.
|
148
|
+
|
149
|
+
For a record to be valid, the value assigned to +captcha_solution=+ must
|
150
|
+
solve the return value of +captcha_challenge+. Within a +with_captcha_validation+
|
151
|
+
block, calling +valid?+ (as is done by +save+, +update_attributes+, etc.)
|
152
|
+
will also validate the value of +captcha_solution+ against +captcha_challenge+.
|
153
|
+
Outside +with_captcha_validation+, no captcha validation is performed.
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
== Question/answer challenge captchas (default provider)
|
158
|
+
|
159
|
+
You can set the captcha provider to use question/answer challenges with
|
160
|
+
the code below. It is best to put this in a Rails initializer.
|
161
|
+
|
162
|
+
ValidatesCaptcha.provider = ValidatesCaptcha::Provider::Question.new # this is the default
|
163
|
+
|
164
|
+
If you want to replace the few default questions and answers, here's how
|
165
|
+
to do it.
|
166
|
+
|
167
|
+
ValidatesCaptcha::Provider::Question.questions_and_answers = {
|
168
|
+
"What's the opposite of bad?" => "good",
|
169
|
+
"What are the initials of the creator of Rails?" => "DHH",
|
170
|
+
"What's the sum of 3 and four?" => ["7", "seven"],
|
171
|
+
... }
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
== Dynamic image challenge captchas
|
176
|
+
|
177
|
+
You can set the captcha provider to use dynamically created image challenges
|
178
|
+
with the code below. Dynamic means that the captcha image is created on invocation.
|
179
|
+
If you want to utilize this provider, it is best to put this in a Rails initializer.
|
180
|
+
|
181
|
+
ValidatesCaptcha.provider = ValidatesCaptcha::Provider::DynamicImage.new
|
182
|
+
|
183
|
+
By default, image captchas have a length of 6 characters and the text displayed
|
184
|
+
on the captcha image is created by randomly selecting characters from a
|
185
|
+
predefined alphabet constisting of visually distinguishable letters and digits.
|
186
|
+
|
187
|
+
The number of characters and the alphabet used when generating strings can
|
188
|
+
be customized. Just put the following in a Rails initializer and adjust the
|
189
|
+
values to your needs.
|
190
|
+
|
191
|
+
ValidatesCaptcha::StringGenerator::Simple.alphabet = '01'
|
192
|
+
ValidatesCaptcha::StringGenerator::Simple.length = 8
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
== Static image challenge captchas
|
197
|
+
|
198
|
+
You can set the captcha provider to use static image challenges with
|
199
|
+
the code below. Static means that there exist some pre-created images
|
200
|
+
in a folder accessible by the web application. If you want to utilize
|
201
|
+
this provider, it is best to put this in a Rails initializer.
|
202
|
+
|
203
|
+
ValidatesCaptcha.provider = ValidatesCaptcha::Provider::StaticImage.new
|
204
|
+
|
205
|
+
There is a Rake tast for creating the static captcha images:
|
206
|
+
|
207
|
+
rake validates_captcha:create_static_images
|
208
|
+
|
209
|
+
This will create 3 images for you. To create a different number of images,
|
210
|
+
provide a COUNT argument:
|
211
|
+
|
212
|
+
rake validates_captcha:create_static_images COUNT=50
|
213
|
+
|
214
|
+
If you want to customize the path the images get saved to (or other stuff),
|
215
|
+
please see the documentation for ValidatesCaptcha::Provider::StaticImage.
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
== Extensibility
|
220
|
+
|
221
|
+
Don't like the built-in challenges? It's easy to extend them or to implement
|
222
|
+
your own.
|
223
|
+
|
224
|
+
Validates Captcha delegates tasks like string and image generation,
|
225
|
+
encryption/decryption of captcha codes, and responding to captcha requests
|
226
|
+
to dedicated backend classes.
|
227
|
+
|
228
|
+
Those classes can easily be replaced with your custom implementations. So
|
229
|
+
you can achieve stronger encryption, can use a word list as image captcha text
|
230
|
+
generation source, or can replace the captcha image generator with one
|
231
|
+
that creates images that are harder to crack.
|
232
|
+
|
233
|
+
Please see the documentation of the following classes for further information.
|
234
|
+
|
235
|
+
* ValidatesCaptcha::StringGenerator::Simple
|
236
|
+
* ValidatesCaptcha::SymmetricEncryptor::Simple
|
237
|
+
* ValidatesCaptcha::ImageGenerator::Simple
|
238
|
+
|
239
|
+
Or you can implement a custom captcha challenge provider and assign it to
|
240
|
+
ValidatesCaptcha#provider=. See the documentation on ValidatesCaptcha::Provider
|
241
|
+
for an example.
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
== Dependencies
|
246
|
+
|
247
|
+
Using a Rack middleware to speed up the request/response cycle when fetching
|
248
|
+
captcha images, Validates Captcha requires Rails version 2.3 or greater.
|
249
|
+
|
250
|
+
The image captcha provider uses ImageMagick's +convert+ command to create
|
251
|
+
the captcha. So a recent and properly configured version of ImageMagick
|
252
|
+
must be installed on the system. The version used while developing was 6.4.5.
|
253
|
+
But you are not bound to ImageMagick. If you want to provide a custom image
|
254
|
+
generator, take a look at the documentation for
|
255
|
+
ValidatesCaptcha::ImageGenerator::Simple on how to create your own.
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
== Installation
|
260
|
+
|
261
|
+
You can install Validates Captcha as a Gem with
|
262
|
+
|
263
|
+
% [sudo] gem install validates_captcha
|
264
|
+
|
265
|
+
and then configure it in your +environment.rb+ file as shown below.
|
266
|
+
|
267
|
+
Rails::Initializer.run do |config|
|
268
|
+
# ...
|
269
|
+
config.gem 'validates_captcha'
|
270
|
+
# ...
|
271
|
+
end
|
272
|
+
|
273
|
+
Or you can install it as a Rails plugin (discouraged) with the
|
274
|
+
following command.
|
275
|
+
|
276
|
+
% ./script/plugin install git://github.com/m4n/validates_captcha.git
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
== Download
|
281
|
+
|
282
|
+
The latest version of Validates Captcha can be found at
|
283
|
+
http://github.com/m4n/validates_captcha
|
284
|
+
|
285
|
+
Documentation can be generated from its distribution directory with the
|
286
|
+
following command.
|
287
|
+
|
288
|
+
% [sudo] rake rdoc
|
289
|
+
|
290
|
+
Tests can be executed from its distribution directory with the
|
291
|
+
following command.
|
292
|
+
|
293
|
+
% [sudo] rake test
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
== Hacking
|
298
|
+
|
299
|
+
Validates Captcha is {hosted on Github}[http://github.com/m4n/validates_captcha].
|
300
|
+
Pull requests are welcome.
|
301
|
+
|
302
|
+
|
303
|
+
|
304
|
+
== Bugs
|
305
|
+
|
306
|
+
Please report bugs on the {Github issue tracker}[http://github.com/m4n/validates_captcha/issues]
|
307
|
+
for this project.
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
== License
|
312
|
+
|
313
|
+
Validates Captcha is released under the MIT license.
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
== Copyright
|
318
|
+
|
319
|
+
Copyright (c) 2009 Martin Andert
|
320
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/packagetask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
require File.join(File.dirname(__FILE__), 'lib', 'validates_captcha', 'version')
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
PKG_NAME = 'validates_captcha'
|
12
|
+
PKG_VERSION = ValidatesCaptcha::VERSION::STRING
|
13
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
14
|
+
|
15
|
+
RELEASE_NAME = "REL #{PKG_VERSION}"
|
16
|
+
|
17
|
+
RUBY_FORGE_PROJECT = 'validatecaptcha'
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
begin
|
22
|
+
require 'hanna/rdoctask'
|
23
|
+
rescue LoadError
|
24
|
+
require 'rake/rdoctask'
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Generate documentation'
|
28
|
+
Rake::RDocTask.new do |rdoc|
|
29
|
+
rdoc.rdoc_dir = 'doc'
|
30
|
+
rdoc.title = "Validates Captcha"
|
31
|
+
rdoc.main = "README.rdoc"
|
32
|
+
|
33
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
34
|
+
rdoc.options << '--charset' << 'utf-8'
|
35
|
+
|
36
|
+
rdoc.rdoc_files.include 'README.rdoc'
|
37
|
+
rdoc.rdoc_files.include 'MIT-LICENSE'
|
38
|
+
rdoc.rdoc_files.include 'CHANGELOG.rdoc'
|
39
|
+
rdoc.rdoc_files.include 'lib/**/*.rb'
|
40
|
+
rdoc.rdoc_files.exclude 'lib/validates_captcha/test_case.rb'
|
41
|
+
rdoc.rdoc_files.exclude 'lib/validates_captcha/version.rb'
|
42
|
+
end
|
43
|
+
|
44
|
+
namespace :rdoc do
|
45
|
+
desc 'Show documentation in Firefox'
|
46
|
+
task :show do
|
47
|
+
sh 'firefox doc/index.html'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
desc 'Run tests by default'
|
54
|
+
task :default => :test
|
55
|
+
|
56
|
+
Rake::TestTask.new do |t|
|
57
|
+
t.libs << 'test'
|
58
|
+
t.test_files = FileList['test/**/*_test.rb']
|
59
|
+
#t.verbose = true
|
60
|
+
#t.warning = true
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
spec = eval(File.read('validates_captcha.gemspec'))
|
66
|
+
|
67
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
68
|
+
pkg.gem_spec = spec
|
69
|
+
pkg.need_tar = true
|
70
|
+
pkg.need_zip = true
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
desc 'Publish the release files to RubyForge'
|
76
|
+
task :release => [:package] do
|
77
|
+
require 'rubyforge'
|
78
|
+
require 'rake/contrib/rubyforgepublisher'
|
79
|
+
|
80
|
+
packages = %w(gem tgz zip).collect { |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" }
|
81
|
+
|
82
|
+
rubyforge = RubyForge.new
|
83
|
+
rubyforge.configure
|
84
|
+
rubyforge.add_release RUBY_FORGE_PROJECT, RUBY_FORGE_PROJECT, RELEASE_NAME, *packages
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
desc 'Uninstall local gem'
|
90
|
+
task :uninstall do
|
91
|
+
system "sudo gem uninstall #{PKG_NAME}"
|
92
|
+
end
|
93
|
+
|
94
|
+
desc 'Install local gem'
|
95
|
+
task :install => [:uninstall, :gem] do
|
96
|
+
system "sudo gem install pkg/#{PKG_NAME}-#{PKG_VERSION}.gem --no-ri --no-rdoc"
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
Dir['tasks/**/*.rake'].each { |tasks_file| load tasks_file }
|
102
|
+
|