mirror of
https://git.kescher.at/CatCatNya/catstodon.git
synced 2024-11-23 16:58:06 +01:00
964ae8eee5
Allow access to account settings, 2FA, authorized applications, and account deletions to unconfirmed and pending users, as well as users who had their accounts disabled. Suspended users cannot update their e-mail or password or delete their account. Display account status on account settings page, for example, when an account is frozen, limited, unconfirmed or pending review. After sign up, login users straight away and show a simple page that tells them the status of their account with links to account settings and logout, to reduce onboarding friction and allow users to correct wrongly typed e-mail addresses. Move the final sign-up step of SSO integrations to be the same as above to reduce code duplication.
132 lines
3.1 KiB
Ruby
132 lines
3.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Auth::SessionsController < Devise::SessionsController
|
|
include Devise::Controllers::Rememberable
|
|
|
|
layout 'auth'
|
|
|
|
skip_before_action :require_no_authentication, only: [:create]
|
|
skip_before_action :require_functional!
|
|
|
|
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
|
|
|
|
before_action :set_instance_presenter, only: [:new]
|
|
before_action :set_body_classes
|
|
|
|
def new
|
|
Devise.omniauth_configs.each do |provider, config|
|
|
return redirect_to(omniauth_authorize_path(resource_name, provider)) if config.strategy.redirect_at_sign_in
|
|
end
|
|
|
|
super
|
|
end
|
|
|
|
def create
|
|
super do |resource|
|
|
remember_me(resource)
|
|
flash.delete(:notice)
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
tmp_stored_location = stored_location_for(:user)
|
|
super
|
|
flash.delete(:notice)
|
|
store_location_for(:user, tmp_stored_location) if continue_after?
|
|
end
|
|
|
|
protected
|
|
|
|
def find_user
|
|
if session[:otp_user_id]
|
|
User.find(session[:otp_user_id])
|
|
elsif user_params[:email]
|
|
if use_seamless_external_login? && Devise.check_at_sign && user_params[:email].index('@').nil?
|
|
User.joins(:account).find_by(accounts: { username: user_params[:email] })
|
|
else
|
|
User.find_for_authentication(email: user_params[:email])
|
|
end
|
|
end
|
|
end
|
|
|
|
def user_params
|
|
params.require(:user).permit(:email, :password, :otp_attempt)
|
|
end
|
|
|
|
def after_sign_in_path_for(resource)
|
|
last_url = stored_location_for(:user)
|
|
|
|
if home_paths(resource).include?(last_url)
|
|
root_path
|
|
else
|
|
last_url || root_path
|
|
end
|
|
end
|
|
|
|
def after_sign_out_path_for(_resource_or_scope)
|
|
Devise.omniauth_configs.each_value do |config|
|
|
return root_path if config.strategy.redirect_at_sign_in
|
|
end
|
|
|
|
super
|
|
end
|
|
|
|
def two_factor_enabled?
|
|
find_user.try(:otp_required_for_login?)
|
|
end
|
|
|
|
def valid_otp_attempt?(user)
|
|
user.validate_and_consume_otp!(user_params[:otp_attempt]) ||
|
|
user.invalidate_otp_backup_code!(user_params[:otp_attempt])
|
|
rescue OpenSSL::Cipher::CipherError => _error
|
|
false
|
|
end
|
|
|
|
def authenticate_with_two_factor
|
|
user = self.resource = find_user
|
|
|
|
if user_params[:otp_attempt].present? && session[:otp_user_id]
|
|
authenticate_with_two_factor_via_otp(user)
|
|
elsif user&.valid_password?(user_params[:password])
|
|
prompt_for_two_factor(user)
|
|
end
|
|
end
|
|
|
|
def authenticate_with_two_factor_via_otp(user)
|
|
if valid_otp_attempt?(user)
|
|
session.delete(:otp_user_id)
|
|
remember_me(user)
|
|
sign_in(user)
|
|
else
|
|
flash.now[:alert] = I18n.t('users.invalid_otp_token')
|
|
prompt_for_two_factor(user)
|
|
end
|
|
end
|
|
|
|
def prompt_for_two_factor(user)
|
|
session[:otp_user_id] = user.id
|
|
render :two_factor
|
|
end
|
|
|
|
private
|
|
|
|
def set_instance_presenter
|
|
@instance_presenter = InstancePresenter.new
|
|
end
|
|
|
|
def set_body_classes
|
|
@body_classes = 'lighter'
|
|
end
|
|
|
|
def home_paths(resource)
|
|
paths = [about_path]
|
|
if single_user_mode? && resource.is_a?(User)
|
|
paths << short_account_path(username: resource.account)
|
|
end
|
|
paths
|
|
end
|
|
|
|
def continue_after?
|
|
truthy_param?(:continue)
|
|
end
|
|
end
|