identity-vault/app/controllers/email_changes_controller.rb
2026-01-01 17:47:36 -05:00

155 lines
5 KiB
Ruby

class EmailChangesController < ApplicationController
skip_before_action :authenticate_identity!, only: [ :verify_old, :verify_new, :confirm_verify_old, :confirm_verify_new ]
before_action :set_email_change_request, only: [ :show, :cancel_confirmation, :cancel ]
before_action :require_step_up_for_email_change, only: [ :new, :create ]
before_action :require_email_change_feature_enabled, except: [ :verify_old, :verify_new, :confirm_verify_old, :confirm_verify_new ]
before_action :require_email_change_feature_enabled_for_verification, only: [ :verify_old, :verify_new, :confirm_verify_old, :confirm_verify_new ]
def new
pending_request = current_identity.email_change_requests.pending.first
if pending_request
redirect_to email_change_path(pending_request), notice: t(".pending_redirect")
return
end
@email_change_request = Identity::EmailChangeRequest.new
end
def show
end
def create
new_email = email_change_params[:new_email]&.downcase&.strip
if new_email.blank?
flash[:error] = t(".email_required")
return redirect_to new_email_change_path
end
existing_pending = current_identity.email_change_requests.pending.first
if existing_pending
existing_pending.cancel!
end
@email_change_request = current_identity.email_change_requests.build(
new_email: new_email,
old_email: current_identity.primary_email,
requested_from_ip: request.remote_ip
)
if @email_change_request.save
@email_change_request.send_verification_emails!
consume_step_up!
flash[:success] = t(".success")
redirect_to email_change_path(@email_change_request)
else
flash[:error] = @email_change_request.errors.full_messages.to_sentence
redirect_to new_email_change_path
end
end
def verify_old
@email_change_request = Identity::EmailChangeRequest.pending.find_by!(old_email_token: params[:token])
@token = params[:token]
rescue ActiveRecord::RecordNotFound
flash[:error] = t(".invalid_or_expired")
redirect_to root_path
end
def confirm_verify_old
@email_change_request = Identity::EmailChangeRequest.pending.find_by!(old_email_token: params[:token])
if @email_change_request.verify_old_email!(params[:token], verified_from_ip: request.remote_ip)
flash[:success] = t("email_changes.verify_old.success")
if @email_change_request.completed?
flash[:success] = t("email_changes.verify_old.email_changed")
end
else
flash[:error] = t("email_changes.verify_old.invalid_or_expired")
end
if identity_signed_in?
redirect_to email_change_path(@email_change_request)
else
redirect_to login_path
end
rescue ActiveRecord::RecordNotFound
flash[:error] = t("email_changes.verify_old.invalid_or_expired")
redirect_to root_path
end
def verify_new
@email_change_request = Identity::EmailChangeRequest.pending.find_by!(new_email_token: params[:token])
@token = params[:token]
rescue ActiveRecord::RecordNotFound
flash[:error] = t(".invalid_or_expired")
redirect_to root_path
end
def confirm_verify_new
@email_change_request = Identity::EmailChangeRequest.pending.find_by!(new_email_token: params[:token])
if @email_change_request.verify_new_email!(params[:token], verified_from_ip: request.remote_ip)
flash[:success] = t("email_changes.verify_new.success")
if @email_change_request.completed?
flash[:success] = t("email_changes.verify_new.email_changed")
end
else
flash[:error] = t("email_changes.verify_new.invalid_or_expired")
end
if identity_signed_in?
redirect_to email_change_path(@email_change_request)
else
redirect_to login_path
end
rescue ActiveRecord::RecordNotFound
flash[:error] = t("email_changes.verify_new.invalid_or_expired")
redirect_to root_path
end
def cancel_confirmation
end
def cancel
if @email_change_request.cancel!
flash[:success] = t(".success")
else
flash[:error] = t(".already_completed")
end
redirect_to edit_identity_path
end
private
def set_email_change_request
@email_change_request = current_identity.email_change_requests.find_by_public_id!(params[:id])
end
def email_change_params
params.require(:email_change).permit(:new_email)
end
def require_step_up_for_email_change
require_step_up("email_change", return_to: new_email_change_path)
end
def require_email_change_feature_enabled
unless Flipper.enabled?(:email_change, current_identity)
redirect_to edit_identity_path, alert: t("errors.feature_not_available")
end
end
def require_email_change_feature_enabled_for_verification
token = params[:token]
email_change_request = Identity::EmailChangeRequest.pending.find_by(old_email_token: token) ||
Identity::EmailChangeRequest.pending.find_by(new_email_token: token)
if email_change_request && !Flipper.enabled?(:email_change, email_change_request.identity)
flash[:error] = t("errors.feature_not_available")
redirect_to root_path
end
end
end