2017-05-15 14:40:07 +00:00
|
|
|
class LoginBannedError < StandardError; end
|
2023-09-01 23:27:36 +00:00
|
|
|
|
2017-05-15 14:40:07 +00:00
|
|
|
class LoginDeletedError < StandardError; end
|
2023-09-01 23:27:36 +00:00
|
|
|
|
2017-05-15 14:40:07 +00:00
|
|
|
class LoginTOTPFailedError < StandardError; end
|
2023-09-01 23:27:36 +00:00
|
|
|
|
2018-11-08 16:50:08 +00:00
|
|
|
class LoginWipedError < StandardError; end
|
2023-09-01 23:27:36 +00:00
|
|
|
|
2017-05-15 14:40:07 +00:00
|
|
|
class LoginFailedError < StandardError; end
|
|
|
|
|
2012-06-17 01:15:46 +00:00
|
|
|
class LoginController < ApplicationController
|
2017-06-18 16:04:32 +00:00
|
|
|
before_action :authenticate_user
|
2023-09-01 23:27:36 +00:00
|
|
|
before_action :check_for_read_only_mode, except: [:index]
|
2019-09-18 13:40:52 +00:00
|
|
|
before_action :require_no_user_or_redirect,
|
2023-09-01 23:27:36 +00:00
|
|
|
only: [:index, :login, :forgot_password, :reset_password]
|
2022-02-24 03:18:50 +00:00
|
|
|
before_action :show_title_h1
|
2012-06-17 01:15:46 +00:00
|
|
|
|
2012-06-30 22:43:45 +00:00
|
|
|
def logout
|
|
|
|
if @user
|
|
|
|
reset_session
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
|
2012-06-30 22:43:45 +00:00
|
|
|
redirect_to "/"
|
|
|
|
end
|
2012-06-17 01:15:46 +00:00
|
|
|
|
2012-06-30 22:43:45 +00:00
|
|
|
def index
|
2012-09-07 14:18:15 +00:00
|
|
|
@title = "Login"
|
2014-08-08 15:31:06 +00:00
|
|
|
@referer ||= request.referer
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def login
|
2023-09-01 23:27:36 +00:00
|
|
|
user = if /@/.match?(params[:email].to_s)
|
|
|
|
User.where(email: params[:email]).first
|
2014-01-12 21:09:32 +00:00
|
|
|
else
|
2023-09-01 23:27:36 +00:00
|
|
|
User.where(username: params[:email]).first
|
2014-01-12 21:09:32 +00:00
|
|
|
end
|
|
|
|
|
2017-05-15 14:40:07 +00:00
|
|
|
fail_reason = nil
|
|
|
|
|
2015-11-18 18:08:45 +00:00
|
|
|
begin
|
|
|
|
if !user
|
2017-05-15 14:40:07 +00:00
|
|
|
raise LoginFailedError
|
2015-11-18 18:08:45 +00:00
|
|
|
end
|
|
|
|
|
2018-11-08 16:50:08 +00:00
|
|
|
if user.is_wiped?
|
|
|
|
raise LoginWipedError
|
|
|
|
end
|
|
|
|
|
2017-03-20 18:24:54 +00:00
|
|
|
if !user.authenticate(params[:password].to_s)
|
2017-11-27 15:57:23 +00:00
|
|
|
raise LoginFailedError
|
2015-11-18 18:08:45 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
if user.is_banned?
|
2017-05-15 14:40:07 +00:00
|
|
|
raise LoginBannedError
|
2015-11-18 18:08:45 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
if !user.is_active?
|
2017-05-15 14:40:07 +00:00
|
|
|
raise LoginDeletedError
|
2015-11-18 18:08:45 +00:00
|
|
|
end
|
|
|
|
|
2023-09-01 23:27:36 +00:00
|
|
|
if !user.password_digest.to_s.match(/^\$2a\$#{BCrypt::Engine::DEFAULT_COST}\$/o)
|
2015-10-11 17:53:07 +00:00
|
|
|
user.password = user.password_confirmation = params[:password].to_s
|
2017-06-22 17:54:03 +00:00
|
|
|
user.save
|
2015-10-11 17:53:07 +00:00
|
|
|
end
|
|
|
|
|
2017-04-13 15:56:03 +00:00
|
|
|
if user.has_2fa? && !Rails.env.development?
|
2017-11-27 15:57:23 +00:00
|
|
|
session[:twofa_u] = user.session_token
|
2017-11-27 19:26:13 +00:00
|
|
|
return redirect_to "/login/2fa"
|
2014-08-08 15:16:06 +00:00
|
|
|
end
|
2014-08-08 15:31:06 +00:00
|
|
|
|
2017-11-27 15:57:23 +00:00
|
|
|
session[:u] = user.session_token
|
2017-03-19 21:50:02 +00:00
|
|
|
|
2017-11-27 15:57:23 +00:00
|
|
|
if (rd = session[:redirect_to]).present?
|
|
|
|
session.delete(:redirect_to)
|
|
|
|
return redirect_to rd
|
|
|
|
elsif params[:referer].present?
|
|
|
|
begin
|
|
|
|
ru = URI.parse(params[:referer])
|
|
|
|
if ru.host == Rails.application.domain
|
|
|
|
return redirect_to ru.to_s
|
|
|
|
end
|
|
|
|
rescue => e
|
|
|
|
Rails.logger.error "error parsing referer: #{e}"
|
|
|
|
end
|
2017-03-19 21:50:02 +00:00
|
|
|
end
|
2017-11-27 15:57:23 +00:00
|
|
|
|
|
|
|
return redirect_to "/"
|
2018-11-08 16:50:08 +00:00
|
|
|
rescue LoginWipedError
|
2023-09-01 23:27:36 +00:00
|
|
|
fail_reason = "Your account was banned or deleted before the site changed admins. " \
|
|
|
|
"Your email and password hash were wiped for privacy."
|
2017-05-15 14:40:07 +00:00
|
|
|
rescue LoginBannedError
|
2022-02-02 03:20:03 +00:00
|
|
|
fail_reason = "Your account has been banned. Log: #{user.banned_reason}"
|
2017-05-15 14:40:07 +00:00
|
|
|
rescue LoginDeletedError
|
|
|
|
fail_reason = "Your account has been deleted."
|
|
|
|
rescue LoginTOTPFailedError
|
|
|
|
fail_reason = "Your TOTP code was invalid."
|
|
|
|
rescue LoginFailedError
|
|
|
|
fail_reason = "Invalid e-mail address and/or password."
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
|
2017-11-27 15:57:23 +00:00
|
|
|
flash.now[:error] = fail_reason
|
|
|
|
@referer = params[:referer]
|
|
|
|
index
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def forgot_password
|
2012-09-07 14:18:15 +00:00
|
|
|
@title = "Reset Password"
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def reset_password
|
2022-02-11 14:07:58 +00:00
|
|
|
@title = "Reset Password"
|
2018-03-14 16:44:26 +00:00
|
|
|
@found_user = User.where("email = ? OR username = ?", params[:email], params[:email]).first
|
2012-06-17 01:15:46 +00:00
|
|
|
|
|
|
|
if !@found_user
|
2020-10-14 01:55:19 +00:00
|
|
|
flash.now[:error] = "Unknown e-mail address or username."
|
2012-06-17 01:15:46 +00:00
|
|
|
return forgot_password
|
|
|
|
end
|
|
|
|
|
2018-11-08 17:28:15 +00:00
|
|
|
if @found_user.is_banned?
|
2019-08-30 02:56:44 +00:00
|
|
|
flash.now[:error] = "Your account has been banned."
|
2018-11-08 17:28:15 +00:00
|
|
|
return forgot_password
|
|
|
|
end
|
|
|
|
|
|
|
|
if @found_user.is_wiped?
|
2023-09-01 23:27:36 +00:00
|
|
|
flash.now[:error] = "It's not possible to reset your password " \
|
|
|
|
"because your account was deleted before the site changed admins " \
|
|
|
|
"and your email address was wiped for privacy."
|
2018-11-08 17:28:15 +00:00
|
|
|
return forgot_password
|
|
|
|
end
|
|
|
|
|
2012-07-03 16:59:50 +00:00
|
|
|
@found_user.initiate_password_reset_for_ip(request.remote_ip)
|
2012-06-17 01:15:46 +00:00
|
|
|
|
2018-03-14 15:15:35 +00:00
|
|
|
flash.now[:success] = "Password reset instructions have been e-mailed to you."
|
2023-09-01 23:27:36 +00:00
|
|
|
index
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def set_new_password
|
2022-02-11 14:07:58 +00:00
|
|
|
@title = "Set New Password"
|
2012-09-07 14:18:15 +00:00
|
|
|
|
2014-04-15 05:46:14 +00:00
|
|
|
if (m = params[:token].to_s.match(/^(\d+)-/)) &&
|
2023-09-01 23:27:36 +00:00
|
|
|
(Time.current - Time.zone.at(m[1].to_i)) < 24.hours
|
|
|
|
@reset_user = User.where(password_reset_token: params[:token].to_s).first
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
|
2015-09-06 19:51:16 +00:00
|
|
|
if @reset_user && !@reset_user.is_banned?
|
2014-04-15 05:46:14 +00:00
|
|
|
if params[:password].present?
|
|
|
|
@reset_user.password = params[:password]
|
|
|
|
@reset_user.password_confirmation = params[:password_confirmation]
|
|
|
|
@reset_user.password_reset_token = nil
|
2021-12-14 23:02:22 +00:00
|
|
|
@reset_user.roll_session_token
|
2012-07-01 18:31:31 +00:00
|
|
|
|
2015-09-06 19:51:16 +00:00
|
|
|
if !@reset_user.is_active? && !@reset_user.is_banned?
|
|
|
|
@reset_user.deleted_at = nil
|
|
|
|
end
|
|
|
|
|
2014-04-15 05:46:14 +00:00
|
|
|
if @reset_user.save && @reset_user.is_active?
|
2017-04-18 17:59:31 +00:00
|
|
|
if @reset_user.has_2fa?
|
|
|
|
flash[:success] = "Your password has been reset."
|
2023-09-01 23:27:36 +00:00
|
|
|
redirect_to "/login"
|
2017-04-18 17:59:31 +00:00
|
|
|
else
|
|
|
|
session[:u] = @reset_user.session_token
|
2023-09-01 23:27:36 +00:00
|
|
|
redirect_to "/"
|
2017-04-18 17:59:31 +00:00
|
|
|
end
|
2015-09-06 19:51:16 +00:00
|
|
|
else
|
|
|
|
flash[:error] = "Could not reset password."
|
2014-04-15 05:46:14 +00:00
|
|
|
end
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
2014-04-15 05:46:14 +00:00
|
|
|
else
|
2023-09-01 23:27:36 +00:00
|
|
|
flash[:error] = "Invalid reset token. It may have already been " \
|
|
|
|
"used or you may have copied it incorrectly."
|
|
|
|
redirect_to forgot_password_path
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|
|
|
|
end
|
2017-02-24 18:58:42 +00:00
|
|
|
|
|
|
|
def twofa
|
2022-02-11 14:07:58 +00:00
|
|
|
@title = "Login - Two Factor Authentication"
|
2018-03-14 17:10:17 +00:00
|
|
|
if (tmpu = find_twofa_user)
|
2023-09-01 23:27:36 +00:00
|
|
|
Rails.logger.info " Authenticated as user #{tmpu.id} " \
|
|
|
|
"(#{tmpu.username}), verifying TOTP"
|
2017-02-24 18:58:42 +00:00
|
|
|
else
|
|
|
|
reset_session
|
2023-09-01 23:27:36 +00:00
|
|
|
redirect_to "/login"
|
2017-02-24 18:58:42 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def twofa_verify
|
2022-02-11 14:07:58 +00:00
|
|
|
@title = "Login - Two Factor Authentication"
|
2017-02-24 18:58:42 +00:00
|
|
|
if (tmpu = find_twofa_user) && tmpu.authenticate_totp(params[:totp_code])
|
|
|
|
session[:u] = tmpu.session_token
|
|
|
|
session.delete(:twofa_u)
|
2023-09-01 23:27:36 +00:00
|
|
|
redirect_to "/"
|
2017-02-24 18:58:42 +00:00
|
|
|
else
|
|
|
|
flash[:error] = "Your TOTP code did not match. Please try again."
|
2023-09-01 23:27:36 +00:00
|
|
|
redirect_to "/login/2fa"
|
2017-02-24 18:58:42 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-09-01 23:27:36 +00:00
|
|
|
private
|
2018-03-02 04:50:11 +00:00
|
|
|
|
2017-02-24 18:58:42 +00:00
|
|
|
def find_twofa_user
|
|
|
|
if session[:twofa_u].present?
|
2023-09-01 23:27:36 +00:00
|
|
|
User.where(session_token: session[:twofa_u]).first
|
2017-02-24 18:58:42 +00:00
|
|
|
end
|
|
|
|
end
|
2012-06-17 01:15:46 +00:00
|
|
|
end
|