blob: 2526d1fbe22999570b903e5e2313e520a29c7315 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
# The second half of a two-step login. A pending marker (set by
# sessions#create after a correct password) plus deadline and attempt
# counter live in the session; the real user_id is only written after a
# valid code, through a fresh session.
class OtpChallengesController < ApplicationController
layout 'admin'
MAX_ATTEMPTS = 5
def new
redirect_to login_path unless pending_user
end
def create
user = pending_user
return redirect_to login_path unless user
session[:otp_attempts] = session[:otp_attempts].to_i + 1
if session[:otp_attempts] > MAX_ATTEMPTS
clear_pending
flash[:error] = t("flash.otp.too_many_attempts")
return redirect_to login_path
end
if user.verify_otp!(params[:code])
return_to = session[:return_to]
reset_session
self.current_user = user
session[:logged_in_at] = Time.now.to_i
# an admin who logs in and goes straight to user management
# is already elevated
elevate! if user.is_admin?
flash[:notice] = if user.is_admin?
t("flash.elevation.granted_at_login",
:minutes => AuthenticatedSystem::ELEVATION_MAX_AGE.in_minutes.to_i)
else
t("flash.common.logged_in")
end
redirect_to safe_return_to(return_to, :default => admin_path)
else
flash.now[:error] = t("flash.otp.code_mismatch")
render :new
end
end
private
def pending_user
return nil if session[:pending_otp_user_id].blank?
if session[:otp_deadline].to_i < Time.now.to_i
clear_pending
return nil
end
@pending_user ||= User.find_by(:id => session[:pending_otp_user_id])
end
def clear_pending
session.delete(:pending_otp_user_id)
session.delete(:otp_deadline)
session.delete(:otp_attempts)
end
end
|