Verify confirmation time frame to let the user sign in or block it if the user is not confirmed.

This commit is contained in:
Carlos A. da Silva 2009-10-21 11:20:10 -02:00
parent 80f3f30704
commit bbca9e830e
8 changed files with 69 additions and 6 deletions

View File

@ -5,6 +5,7 @@ class SessionsController < ApplicationController
# GET /resource/sign_in
def new
unauthenticated! if params[:unauthenticated]
unconfirmed! if params[:unconfirmed]
end
# POST /resource/sign_in
@ -28,8 +29,11 @@ class SessionsController < ApplicationController
protected
def unauthenticated!
flash.now[:failure] = I18n.t(:"#{resource_name}.unauthenticated",
:scope => [:devise, :sessions], :default => :unauthenticated)
set_now_flash_message :failure, :unauthenticated
end
def unconfirmed!
set_now_flash_message :failure, :unconfirmed
end
end

View File

@ -4,6 +4,7 @@ en:
signed_in: 'Signed in successfully.'
signed_out: 'Signed out successfully.'
unauthenticated: 'Invalid email or password.'
unconfirmed: 'Your account was not confirmed and your confirmation period has expired.'
passwords:
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
updated: 'Your password was changed successfully. You are now signed in.'

View File

@ -58,6 +58,9 @@ module Devise
include Devise::Models.const_get(m.to_s.classify)
end
# Assert valid keys after including modules to ensure MODEL_CONFIG is fully loaded
options.assert_valid_keys(:except, *Devise::MODEL_CONFIG)
# Convert new keys to methods which overwrites Devise defaults
options.each { |key, value| send(:"#{key}=", value) }
end

View File

@ -81,11 +81,17 @@ module Devise
#
# Please refer to README or en.yml locale file to check what messages are
# available.
def set_flash_message(key, kind)
flash[key] = I18n.t(:"#{resource_name}.#{kind}",
def set_flash_message(key, kind, now=false)
flash_hash = now ? flash.now : flash
flash_hash[key] = I18n.t(:"#{resource_name}.#{kind}",
:scope => [:devise, controller_name.to_sym], :default => kind)
end
# Shortcut to set flash.now message. Same rules applied from set_flash_message
def set_now_flash_message(key, kind)
set_flash_message(key, kind, true)
end
end
end
end

View File

@ -0,0 +1,20 @@
# Each time the user is set we verify if it is still able to really sign in.
# This is done by checking the time frame the user is able to sign in without
# confirming it's account. If the user has not confirmed it's account during
# this time frame, he/she will not able to sign in anymore.
Warden::Manager.after_set_user do |record, auth, options|
if record.present? && record.respond_to?(:active?) && !record.active?
scope = options[:scope]
mapping = Devise.mappings[scope]
auth.logout(scope)
# TODO: Change the way we handle redirect here after updating warden
throw :warden, [
302,
{
'Location' => "/#{mapping.as}/#{mapping.path_names[:sign_in]}?unconfirmed=true",
'Content-Type' => 'text/plain'
},
['You are being redirected']
]
end
end

View File

@ -19,6 +19,6 @@ end
Warden::Manager.before_logout do |record, auth, scope|
if record.respond_to?(:forget_me!)
record.forget_me!
auth.cookies['remember_token'] = nil
auth.cookies.delete('remember_token')
end
end

View File

@ -82,7 +82,7 @@ module Devise
# confirmation_period_valid? # will always return false
def confirmation_period_valid?
confirmation_sent_at? &&
(Date.today - confirmation_sent_at.to_date).days.to_i < confirm_in
(Date.today - confirmation_sent_at.to_date).days.to_i < confirm_in.to_i
end
# Checks whether the record is confirmed or not, yielding to the block

View File

@ -57,4 +57,33 @@ class ConfirmationTest < ActionController::IntegrationTest
assert warden.authenticated?(:user)
end
test 'not confirmed user and setup to block without confirmation should not be able to sign in' do
Devise.confirm_in = 0
user = sign_in_as_user(:confirm => false)
assert_redirected_to new_user_session_path(:unconfirmed => true)
assert_not warden.authenticated?(:user)
end
test 'not confirmed user but configured with some days to confirm should be able to sign in' do
Devise.confirm_in = 1
user = sign_in_as_user(:confirm => false)
assert_response :success
assert warden.authenticated?(:user)
end
test 'error message is configurable by resource name' do
begin
I18n.backend.store_translations(:en, :devise => { :sessions =>
{ :admin => { :unconfirmed => "Not confirmed user" } } })
get new_admin_session_path(:unconfirmed => true)
assert_contain 'Not confirmed user'
ensure
I18n.reload!
end
end
end