Commit 920f13a937341eb52a0b26d4924cf399fc994b52
1 parent
05dbd36f
Exists in
master
and in
29 other branches
Force minimum signup time to block bots. Also add captcha for fast submitters
ActionItem2556
Showing
5 changed files
with
88 additions
and
15 deletions
Show diff stats
app/controllers/public/account_controller.rb
... | ... | @@ -56,8 +56,8 @@ class AccountController < ApplicationController |
56 | 56 | end |
57 | 57 | |
58 | 58 | def signup_time |
59 | - set_signup_time_for_now | |
60 | - render :text => {:ok=>true}.to_json | |
59 | + key = set_signup_start_time_for_now | |
60 | + render :text => { :ok=>true, :key=>key }.to_json | |
61 | 61 | end |
62 | 62 | |
63 | 63 | # action to register an user to the application |
... | ... | @@ -83,12 +83,12 @@ class AccountController < ApplicationController |
83 | 83 | @person.environment = @user.environment |
84 | 84 | if request.post? |
85 | 85 | if may_be_a_bot |
86 | - set_signup_time_for_now | |
86 | + set_signup_start_time_for_now | |
87 | 87 | @block_bot = true |
88 | 88 | session[:may_be_a_bot] = true |
89 | 89 | else |
90 | 90 | if session[:may_be_a_bot] |
91 | - return false unless verify_recaptcha :model=>@user, :message=>_('bota o recaptcha manuel!') | |
91 | + return false unless verify_recaptcha :model=>@user, :message=>_('Captcha (the human test)') | |
92 | 92 | end |
93 | 93 | @user.signup! |
94 | 94 | owner_role = Role.find_by_name('owner') |
... | ... | @@ -112,6 +112,7 @@ class AccountController < ApplicationController |
112 | 112 | @person.errors.delete(:user_id) |
113 | 113 | render :action => 'signup' |
114 | 114 | end |
115 | + clear_signup_start_time | |
115 | 116 | end |
116 | 117 | |
117 | 118 | # action to perform logout from the application |
... | ... | @@ -287,13 +288,33 @@ class AccountController < ApplicationController |
287 | 288 | @cannot_redirect = true |
288 | 289 | end |
289 | 290 | |
290 | - def set_signup_time_for_now | |
291 | - session[:signup_time] = Time.now | |
291 | + def set_signup_start_time_for_now | |
292 | + key = 'signup_start_time_' + rand.to_s.split('.')[1] | |
293 | + Rails.cache.write key, Time.now | |
294 | + key | |
295 | + end | |
296 | + | |
297 | + def get_signup_start_time | |
298 | + Rails.cache.read params[:signup_time_key] | |
299 | + end | |
300 | + | |
301 | + def clear_signup_start_time | |
302 | + Rails.cache.delete params[:signup_time_key] | |
292 | 303 | end |
293 | 304 | |
294 | 305 | def may_be_a_bot |
295 | - return true if session[:signup_time].nil? | |
296 | - session[:signup_time] > ( Time.now - 15.seconds ) | |
306 | + # No minimum signup delay, no bot test. | |
307 | + return false if environment.min_signup_delay == 0 | |
308 | + | |
309 | + # answering captcha, may be human! | |
310 | + return false if params[:recaptcha_response_field] | |
311 | + | |
312 | + # never set signup_time, hi wget! | |
313 | + signup_start_time = get_signup_start_time | |
314 | + return true if signup_start_time.nil? | |
315 | + | |
316 | + # so fast, so bot. | |
317 | + signup_start_time > ( Time.now - environment.min_signup_delay.seconds ) | |
297 | 318 | end |
298 | 319 | |
299 | 320 | def check_answer | ... | ... |
app/models/environment.rb
... | ... | @@ -233,6 +233,7 @@ class Environment < ActiveRecord::Base |
233 | 233 | settings[:message_for_member_invitation] || InviteMember.mail_template |
234 | 234 | end |
235 | 235 | |
236 | + settings_items :min_signup_delay, :type => Integer, :default => 25 #seconds | |
236 | 237 | settings_items :activation_blocked_text, :type => String |
237 | 238 | settings_items :message_for_disabled_enterprise, :type => String, |
238 | 239 | :default => _('This enterprise needs to be enabled.') | ... | ... |
app/views/account/_signup_form.rhtml
1 | -<script type="text/javascript"> | |
2 | - jQuery.post("<%= url_for :controller=>'account', :action=>'signup_time' %>"); | |
3 | -</script> | |
4 | - | |
5 | 1 | <% if @block_bot %> |
6 | - <div class="bot-notice"> | |
7 | - <%=_('<strong>How Fast!</strong> Looks like you are a bot.')%> | |
2 | + <div id="bot-notice"> | |
3 | + <strong><%=_('How Fast!')%></strong> | |
4 | + <p><%=_('Looks like you are a robot. Please, prove that you are human.')%></p> | |
8 | 5 | </div> |
9 | 6 | <% end %> |
10 | 7 | |
... | ... | @@ -14,6 +11,18 @@ |
14 | 11 | |
15 | 12 | <% labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form' } do |f| %> |
16 | 13 | |
14 | +<input type="hidden" id="signup_time_key" name="signup_time_key" /> | |
15 | +<script type="text/javascript"> | |
16 | + jQuery.ajax({ | |
17 | + type: "POST", | |
18 | + url: "<%= url_for :controller=>'account', :action=>'signup_time' %>", | |
19 | + dataType: 'json', | |
20 | + success: function(data) { | |
21 | + if (data.ok) jQuery('#signup_time_key').val(data.key); | |
22 | + } | |
23 | + }); | |
24 | +</script> | |
25 | + | |
17 | 26 | <%= hidden_field_tag :invitation_code, @invitation_code %> |
18 | 27 | |
19 | 28 | <div id='signup-form-header'> | ... | ... |
public/stylesheets/application.css
... | ... | @@ -5636,6 +5636,16 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { |
5636 | 5636 | |
5637 | 5637 | /* Signup interface {{{ */ |
5638 | 5638 | |
5639 | +#bot-notice { | |
5640 | + border: 3px solid #000; | |
5641 | + background: #FE0; | |
5642 | + padding: 5px 10px; | |
5643 | + font-size: 150%; | |
5644 | +} | |
5645 | +#bot-notice p { | |
5646 | + margin: 0px; | |
5647 | +} | |
5648 | + | |
5639 | 5649 | #url-check { |
5640 | 5650 | margin: 0 0 -5px 0; |
5641 | 5651 | width: 100%; | ... | ... |
test/integration/signup_test.rb
... | ... | @@ -7,8 +7,40 @@ class SignupTest < ActionController::IntegrationTest |
7 | 7 | ActionController::Integration::Session.any_instance.stubs(:https?).returns(true) |
8 | 8 | end |
9 | 9 | |
10 | + # helper | |
11 | + def registering_with_bot_test(min_signup_delay, sleep_secs) | |
12 | + env = Environment.default | |
13 | + env.min_signup_delay = min_signup_delay | |
14 | + env.save! | |
15 | + get '/account/signup' | |
16 | + assert_response :success | |
17 | + get '/account/signup_time' | |
18 | + assert_response :success | |
19 | + data = ActiveSupport::JSON.decode response.body | |
20 | + sleep sleep_secs | |
21 | + post '/account/signup', :user => { :login => 'someone', :password => 'test', :password_confirmation => 'test', :email => 'someone@example.com' }, :signup_time_key => data['key'] | |
22 | + assert_response :success | |
23 | + end | |
24 | + | |
25 | + def test_signup_form_submition_must_be_blocked_for_fast_bots | |
26 | + count = User.count | |
27 | + registering_with_bot_test 5, 1 | |
28 | + assert_template 'signup' | |
29 | + assert_equal count, User.count | |
30 | + assert_match /you are a robot/, response.body | |
31 | + end | |
32 | + | |
33 | + def test_signup_form_submition_must_not_block_after_min_signup_delay | |
34 | + count = User.count | |
35 | + registering_with_bot_test 1, 2 | |
36 | + assert_equal count+1, User.count | |
37 | + end | |
38 | + | |
10 | 39 | def test_should_require_acceptance_of_terms_for_signup |
11 | - Environment.default.update_attributes(:terms_of_use => 'You agree to not be annoying.') | |
40 | + env = Environment.default | |
41 | + env.update_attributes(:terms_of_use => 'You agree to not be annoying.') | |
42 | + env.min_signup_delay = 0 | |
43 | + env.save! | |
12 | 44 | |
13 | 45 | count = User.count |
14 | 46 | mail_count = ActionMailer::Base.deliveries.count | ... | ... |