2012-07-01 20:31:31 +02:00
|
|
|
class SettingsController < ApplicationController
|
|
|
|
before_filter :require_logged_in_user
|
|
|
|
|
2017-05-17 11:29:54 +02:00
|
|
|
TOTP_SESSION_TIMEOUT = (60 * 15)
|
|
|
|
|
2012-07-01 20:31:31 +02:00
|
|
|
def index
|
2016-07-09 14:31:32 +02:00
|
|
|
@title = t('.accountsettings')
|
2012-09-07 16:18:15 +02:00
|
|
|
|
2012-07-01 20:31:31 +02:00
|
|
|
@edit_user = @user.dup
|
|
|
|
end
|
|
|
|
|
2014-01-13 17:12:17 +01:00
|
|
|
def delete_account
|
|
|
|
if @user.try(:authenticate, params[:user][:password].to_s)
|
|
|
|
@user.delete!
|
|
|
|
reset_session
|
2016-07-09 14:31:32 +02:00
|
|
|
flash[:success] = t('.deleteaccountflash')
|
2014-01-13 17:12:17 +01:00
|
|
|
return redirect_to "/"
|
|
|
|
end
|
|
|
|
|
2016-07-09 14:31:32 +02:00
|
|
|
flash[:error] = t('.verifypasswordflash')
|
2015-01-03 01:33:13 +01:00
|
|
|
return redirect_to settings_path
|
2014-01-13 17:12:17 +01:00
|
|
|
end
|
|
|
|
|
2012-07-01 20:31:31 +02:00
|
|
|
def update
|
|
|
|
@edit_user = @user.clone
|
|
|
|
|
2017-05-17 19:36:41 +02:00
|
|
|
if params[:user][:password].empty? ||
|
|
|
|
@user.authenticate(params[:current_password].to_s)
|
|
|
|
if @edit_user.update_attributes(user_params)
|
|
|
|
flash.now[:success] = t('.updatesettingsflash')
|
|
|
|
@user = @edit_user
|
|
|
|
end
|
|
|
|
else
|
|
|
|
flash[:error] = t('.passwordnotcorrect')
|
2012-07-01 20:31:31 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
render :action => "index"
|
|
|
|
end
|
2014-02-02 21:41:38 +01:00
|
|
|
|
2017-05-17 11:29:54 +02:00
|
|
|
def twofa
|
2017-05-17 18:13:24 +02:00
|
|
|
@title = t('.title')
|
2017-05-17 11:29:54 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def twofa_auth
|
|
|
|
if @user.authenticate(params[:user][:password].to_s)
|
|
|
|
session[:last_authed] = Time.now.to_i
|
|
|
|
session.delete(:totp_secret)
|
|
|
|
|
|
|
|
if @user.has_2fa?
|
|
|
|
@user.disable_2fa!
|
2017-05-17 18:13:24 +02:00
|
|
|
flash[:success] = t('.2fahasbeendisabled')
|
2017-05-17 11:29:54 +02:00
|
|
|
return redirect_to "/settings"
|
|
|
|
else
|
|
|
|
return redirect_to twofa_enroll_url
|
|
|
|
end
|
|
|
|
else
|
2017-05-17 18:13:24 +02:00
|
|
|
flash[:error] = t('.2fapassnotcorrect')
|
2017-05-17 11:29:54 +02:00
|
|
|
return redirect_to twofa_url
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def twofa_enroll
|
2017-05-17 18:13:24 +02:00
|
|
|
@title = t('.title')
|
2017-05-17 11:29:54 +02:00
|
|
|
|
|
|
|
if (Time.now.to_i - session[:last_authed].to_i) > TOTP_SESSION_TIMEOUT
|
2017-05-17 18:13:24 +02:00
|
|
|
flash[:error] = t('.enrollmenttimeout')
|
2017-05-17 11:29:54 +02:00
|
|
|
return redirect_to twofa_url
|
|
|
|
end
|
|
|
|
|
|
|
|
if !session[:totp_secret]
|
|
|
|
session[:totp_secret] = ROTP::Base32.random_base32
|
|
|
|
end
|
|
|
|
|
|
|
|
totp = ROTP::TOTP.new(session[:totp_secret],
|
|
|
|
:issuer => Rails.application.name)
|
|
|
|
totp_url = totp.provisioning_uri(@user.email)
|
|
|
|
|
|
|
|
# no option for inline svg, so just strip off leading <?xml> tag
|
|
|
|
qrcode = RQRCode::QRCode.new(totp_url)
|
|
|
|
qr = qrcode.as_svg(:offset => 0, color: "000", :module_size => 5,
|
|
|
|
:shape_rendering => "crispEdges").gsub(/^<\?xml.*>/, "")
|
|
|
|
|
|
|
|
@qr_svg = "<a href=\"#{totp_url}\">#{qr}</a>"
|
|
|
|
end
|
|
|
|
|
|
|
|
def twofa_verify
|
2017-05-17 18:13:24 +02:00
|
|
|
@title = t('.title')
|
2017-05-17 11:29:54 +02:00
|
|
|
|
|
|
|
if ((Time.now.to_i - session[:last_authed].to_i) > TOTP_SESSION_TIMEOUT) ||
|
|
|
|
!session[:totp_secret]
|
2017-05-17 18:13:24 +02:00
|
|
|
flash[:error] = t('.enrollmenttimeout')
|
2017-05-17 11:29:54 +02:00
|
|
|
return redirect_to twofa_url
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def twofa_update
|
|
|
|
if ((Time.now.to_i - session[:last_authed].to_i) > TOTP_SESSION_TIMEOUT) ||
|
|
|
|
!session[:totp_secret]
|
2017-05-17 18:13:24 +02:00
|
|
|
flash[:error] = t('.enrollmenttimeout')
|
2017-05-17 11:29:54 +02:00
|
|
|
return redirect_to twofa_url
|
|
|
|
end
|
|
|
|
|
|
|
|
@user.totp_secret = session[:totp_secret]
|
|
|
|
if @user.authenticate_totp(params[:totp_code])
|
|
|
|
# re-roll, just in case
|
|
|
|
@user.session_token = nil
|
|
|
|
@user.save!
|
|
|
|
|
|
|
|
session[:u] = @user.session_token
|
|
|
|
|
2017-05-17 18:13:24 +02:00
|
|
|
flash[:success] = t('.2fahasbeenenabled')
|
2017-05-17 11:29:54 +02:00
|
|
|
session.delete(:totp_secret)
|
|
|
|
return redirect_to "/settings"
|
|
|
|
else
|
2017-05-17 18:13:24 +02:00
|
|
|
flash[:error] = t('.totpinvalid')
|
2017-05-17 11:29:54 +02:00
|
|
|
return redirect_to twofa_verify_url
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-05-20 13:40:52 +02:00
|
|
|
# external services
|
|
|
|
|
|
|
|
def pushover_auth
|
|
|
|
if !Pushover.SUBSCRIPTION_CODE
|
|
|
|
flash[:error] = "This site is not configured for Pushover"
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
session[:pushover_rand] = SecureRandom.hex
|
|
|
|
|
|
|
|
return redirect_to Pushover.subscription_url({
|
|
|
|
:success => "#{Rails.application.root_url}settings/pushover_callback?" <<
|
|
|
|
"rand=#{session[:pushover_rand]}",
|
|
|
|
:failure => "#{Rails.application.root_url}settings/",
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
def pushover_callback
|
|
|
|
if !session[:pushover_rand].to_s.present?
|
|
|
|
flash[:error] = "No random token present in session"
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
if !params[:rand].to_s.present?
|
|
|
|
flash[:error] = "No random token present in URL"
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
if params[:rand].to_s != session[:pushover_rand].to_s
|
|
|
|
raise "rand param #{params[:rand].inspect} != " <<
|
|
|
|
session[:pushover_rand].inspect
|
|
|
|
end
|
|
|
|
|
|
|
|
@user.pushover_user_key = params[:pushover_user_key].to_s
|
|
|
|
@user.save!
|
|
|
|
|
|
|
|
if @user.pushover_user_key.present?
|
|
|
|
flash[:success] = "Your account is now setup for Pushover notifications."
|
|
|
|
else
|
|
|
|
flash[:success] = "Your account is no longer setup for Pushover " <<
|
|
|
|
"notifications."
|
|
|
|
end
|
|
|
|
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
def github_auth
|
|
|
|
session[:github_state] = SecureRandom.hex
|
|
|
|
return redirect_to Github.oauth_auth_url(session[:github_state])
|
|
|
|
end
|
|
|
|
|
|
|
|
def github_callback
|
|
|
|
if !session[:github_state].present? || !params[:code].present? ||
|
|
|
|
(params[:state].to_s != session[:github_state].to_s)
|
2017-05-23 10:41:09 +02:00
|
|
|
flash[:error] = "Invalid OAuth state"
|
2017-05-20 13:40:52 +02:00
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
session.delete(:github_state)
|
|
|
|
|
|
|
|
tok, username = Github.token_and_user_from_code(params[:code])
|
|
|
|
if tok.present? && username.present?
|
|
|
|
@user.github_oauth_token = tok
|
|
|
|
@user.github_username = username
|
|
|
|
@user.save!
|
|
|
|
flash[:success] = "Your account has been linked to GitHub user " <<
|
|
|
|
"#{username}."
|
|
|
|
else
|
|
|
|
return github_disconnect
|
|
|
|
end
|
|
|
|
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
def github_disconnect
|
|
|
|
@user.github_oauth_token = nil
|
|
|
|
@user.github_username = nil
|
|
|
|
@user.save!
|
|
|
|
flash[:success] = "Your GitHub association has been removed."
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
2017-05-23 10:41:09 +02:00
|
|
|
def twitter_auth
|
|
|
|
session[:twitter_state] = SecureRandom.hex
|
|
|
|
return redirect_to Twitter.oauth_auth_url(session[:twitter_state])
|
|
|
|
end
|
|
|
|
|
|
|
|
def twitter_callback
|
|
|
|
if !session[:twitter_state].present? ||
|
|
|
|
(params[:state].to_s != session[:twitter_state].to_s)
|
|
|
|
flash[:error] = "Invalid OAuth state"
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
session.delete(:twitter_state)
|
|
|
|
|
|
|
|
tok, sec, username = Twitter.token_secret_and_user_from_token_and_verifier(
|
|
|
|
params[:oauth_token], params[:oauth_verifier])
|
|
|
|
if tok.present? && username.present?
|
|
|
|
@user.twitter_oauth_token = tok
|
|
|
|
@user.twitter_oauth_token_secret = sec
|
|
|
|
@user.twitter_username = username
|
|
|
|
@user.save!
|
|
|
|
flash[:success] = "Your account has been linked to Twitter user @" <<
|
|
|
|
"#{username}."
|
|
|
|
else
|
|
|
|
return twitter_disconnect
|
|
|
|
end
|
|
|
|
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
|
|
|
def twitter_disconnect
|
|
|
|
@user.twitter_oauth_token = nil
|
|
|
|
@user.twitter_username = nil
|
|
|
|
@user.twitter_oauth_token_secret = nil
|
|
|
|
@user.save!
|
|
|
|
flash[:success] = "Your Twitter association has been removed."
|
|
|
|
return redirect_to "/settings"
|
|
|
|
end
|
|
|
|
|
2014-02-02 21:41:38 +01:00
|
|
|
private
|
|
|
|
|
|
|
|
def user_params
|
|
|
|
params.require(:user).permit(
|
|
|
|
:username, :email, :password, :password_confirmation, :about,
|
|
|
|
:email_replies, :email_messages, :email_mentions,
|
|
|
|
:pushover_replies, :pushover_messages, :pushover_mentions,
|
2015-12-07 19:25:23 +01:00
|
|
|
:mailing_list_mode, :show_avatars, :show_story_previews,
|
2017-05-17 10:23:25 +02:00
|
|
|
:show_submitted_story_threads, :hide_dragons
|
2014-02-02 21:41:38 +01:00
|
|
|
)
|
|
|
|
end
|
2012-07-01 20:31:31 +02:00
|
|
|
end
|