[英]Devise not confirming email on update
我正在使用 devise 進行身份驗證。 我正在覆蓋 devise 令牌生成器,以便我可以使用 6 位代碼並覆蓋它,以便我可以支持手機號碼確認。
如果用戶注冊 email 並且 OTP 通過 email 發送。 注冊似乎工作正常。 用戶注冊 email。 發送 OTP 並在確認后確認用戶。
但是當用戶嘗試更新 email 時。 我使用相同的方法來發送確認碼(就像在注冊中一樣),用戶被保存在 unconfirmed_email 中。 郵件在 email 中發送,但在確認后,用戶 email 未從 unconfirmed_email 字段復制到 email 字段。
這里可能是什么問題。
應用程序/服務/用戶/confirmation_code_sender.rb
# frozen_string_literal: true
module Users
class ConfirmationCodeSender
attr_reader :user
def initialize(id:)
@user = User.find(id)
end
# rubocop :disable Metrics/AbcSize
def call
generate_confirmation_token!
if user.email?
DeviseMailer.confirmation_instructions(
user,
user.confirmation_token,
{ to: user.unconfirmed_email || user.email }
).deliver_now
else
Telco::Web::Sms.send_text(recipient: user.unconfirmed_mobile || user.mobile_number, message: sms_text)
end
end
# rubocop :enable Metrics/AbcSize
private
def generate_confirmation_token!
user.confirmation_token = TokenGenerator.token(6)
user.confirmation_sent_at = DateTime.current
user.save!(validate: false)
end
def sms_text
I18n.t('sms.confirmation_token', token: user.confirmation_token)
end
end
end
應用程序/服務/用戶/phone_or_email_updater.rb
# frozen_string_literal: true
module Users
class PhoneOrEmailUpdater < BaseService
def call
authorize!(current_user, to: :user?)
current_user.tap do |user|
user.update!(unconfirmed_mobile: params[:unconfirmed_mobile], unconfirmed_email: params[:unconfirmed_email])
ConfirmationCodeSender.new(id: user.id).call
end
end
end
end
配置/初始化器/confirmable.rb
# frozen_string_literal: true
# Overriding this model to support the confirmation for mobile number as well
module Devise
module Models
module Confirmable
def confirm(args = {})
pending_any_confirmation do
return expired_error if confirmation_period_expired?
self.confirmed_at = Time.now.utc
saved = saved(args)
after_confirmation if saved
saved
end
end
def saved(args)
@saved ||= if pending_reconfirmation?
skip_reconfirmation!
save!(validate: true)
else
save!(validate: args[:ensure_valid] == true)
end
end
def pending_reconfirmation?
if unconfirmed_email.present?
self.email = unconfirmed_email
self.unconfirmed_email = nil
true
elsif unconfirmed_mobile.present?
self.mobile_number = unconfirmed_mobile
self.unconfirmed_mobile = nil
true
else
false
end
end
private
def expired_error
errors.add(
:email,
:confirmation_period_expired,
period: Devise::TimeInflector.time_ago_in_words(self.class.confirm_within.ago)
)
false
end
end
end
end
移動更新似乎工作正常,但 email 沒有更新。 我正在使用 graphql 來更新 email
在控制台中我嘗試使用.confirm
但它似乎無法正常工作,用戶 email 沒有得到確認
在您的pending_reconfirmation?
, self.unconfirmed_email
被指定為nil
。 好像是pending_reconfirmation?
僅在saved
中調用,但是也由pending_any_confirmation
調用。
# Checks whether the record requires any confirmation.
def pending_any_confirmation
if (!confirmed? || pending_reconfirmation?)
yield
else
self.errors.add(:email, :already_confirmed)
false
end
end
那么第二次pending_reconfirmation?
在saved
的,pending_reconfirmation 中調用? 將返回 false,因為 unconfirmed_email 為 nil。
您最好不要在以?
結尾的方法中進行實際分配。 這將是一個隱含的副作用。 也許創建一個以!
結尾的新方法改變屬性的值。
例如:
module Devise
module Models
module Confirmable
def confirm(args = {})
pending_any_confirmation do
return expired_error if confirmation_period_expired?
self.confirmed_at = Time.now.utc
saved = saved(args)
after_confirmation if saved
saved
end
end
def saved(args)
@saved ||= if pending_reconfirmation?
reconfirm_email! if unconfirmed_email.present?
reconfirm_mobile! if unconfirmed_mobile.present?
skip_reconfirmation!
save!(validate: true)
else
save!(validate: args[:ensure_valid] == true)
end
end
def pending_reconfirmation?
unconfirmed_email.present? || nconfirmed_mobile.present?
end
def reconfirm_email!
self.email = unconfirmed_email
self.unconfirmed_email = nil
end
def reconfirm_mobile!
self.mobile_number = unconfirmed_mobile
self.unconfirmed_mobile = nil
end
private
def expired_error
errors.add(
:email,
:confirmation_period_expired,
period: Devise::TimeInflector.time_ago_in_words(self.class.confirm_within.ago)
)
false
end
end
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.