Mailer не может получить доступ к reset_token в модели пользователя

столкнулся с проблемой, когда @user.reset_token возвращает ноль.

приложение/представления/user_mailer/password_reset.html.erb

<%= link_to "Reset password", edit_password_reset_url(@user.reset_token, email: @user.email) %>

Reset_token объявлен в модели пользователя, из-за чего эта проблема возникает, когда я пытаюсь использовать воркер sidekiq. См. код ниже.

приложение/модели/user.rb

class User < ActiveRecord::Base

attr_accessor :reset_token

  def User.new_token
    SecureRandom.urlsafe_base64
  end  

  def send_password_reset_email
    PasswordResetWorker.perform_async(self.id)
  end  

private

  def create_reset_digest
    self.reset_token = User.new_token
    update_attribute(:reset_digest,  User.digest(reset_token))
    update_attribute(:reset_sent_at, Time.zone.now)
  end 

приложение/рабочие/password_reset_worker.rb

class PasswordResetWorker
  include Sidekiq::Worker
  sidekiq_options retry: false

  def perform(user_id)
    user = User.find(user_id)
    UserMailer.password_reset(user).deliver
  end
end

приложение/почтовые программы/user_mailer.rb

class UserMailer < ActionMailer::Base
  default from: "[email protected]"

  def password_reset(user)
    @user = user
    mail to: user.email, subject: "Password Reset"
  end
end

Эта проблема НЕ возникает, когда я не использую воркеры

приложение/модели/user.rb

  def send_password_reset_email
    UserMailer.password_reset(self).deliver
  end

Хотели бы знать, чем я могу заменить «@user.reset_token»? Дайте мне знать, если вам нужна дополнительная информация. Заранее спасибо.


person chickensmitten    schedule 11.01.2015    source источник
comment
Функция сброса пароля создана в соответствии с railstutorial.org/book/account_activation_password_reset. Я только хочу добавить sidekiq для этого.   -  person chickensmitten    schedule 11.01.2015


Ответы (1)


Вы не храните reset_token в базе данных — вы сохраняете reset_digest.

Когда вы не используете воркеров, вы сохраняете reset_token в экземпляре пользователя, а затем передаете тот же самый экземпляр пользователя в свою почтовую программу, поэтому reset_token по-прежнему доступен.

Когда вы используете воркеров, ваш воркер имеет только идентификатор пользователя, поэтому он перезагружает экземпляр пользователя из базы данных. Поскольку reset_token не хранится в базе данных, он возвращается к нулю.

Либо вы должны сохранить reset_token в базе данных, либо ваш адрес электронной почты с паролем должен использовать reset_digest в URL-адресе.

person sevenseacat    schedule 11.01.2015
comment
Эй, спасибо! Да, я так и подозревал. Есть ли шанс, что я все еще могу сделать это без необходимости сохранять reset_token в базе данных или использовать reset_digest? Я думаю, что это сделано так для безопасности. - person chickensmitten; 11.01.2015
comment
Хранение токенов и последующее их использование для аутентификации допустимо, если токен достаточно сложен. - person sevenseacat; 11.01.2015
comment
Если вы действительно беспокоитесь о безопасности, вы можете передать сгенерированный reset_token в качестве дополнительного параметра рабочему процессу Sidekiq. Однако прямого использования токенов достаточно, поскольку сброс пароля должен быть недолговечным с относительно коротким сроком действия. - person sevenseacat; 11.01.2015