【问题标题】:Is there a solution for Rails Gem Devise to allow a user to have multiple emails?Rails Gem Devise 是否有允许用户拥有多封电子邮件的解决方案?
【发布时间】:2013-04-29 17:50:04
【问题描述】:

我正在寻找一种解决方案,以允许我的应用上的用户拥有超过 1 封电子邮件。这应该类似于 Facebook、LinkedIn 和 Quora。一个帐户可以有多个电子邮件,其中 1 个作为主要电子邮件。

是否有可供设计的交钥匙解决方案?鉴于它很常见,我希望不必从头开始编写。

想法?谢谢

【问题讨论】:

  • 您是否也想为任何用户启用使用这些辅助电子邮件的登录功能?
  • 是的,用户应该只能使用他们的任何电子邮件登录。此外,电子邮件不应该能够共存,整个系统中每个帐户的唯一电子邮件......就像 Facebook 如何处理这个......
  • 我不知道现有的解决方案,但如果您决定自己编写,您可以从这个开始,这至少是相似的(多个可能的登录值):github.com/plataformatec/devise/wiki/…

标签: ruby-on-rails ruby-on-rails-3 devise


【解决方案1】:

嗯...我建议创建新模型,您将执行以下操作:

例如模型是UserEmail

class UserEmail < ActiveRecord::Base
    belongs_to :user
end

class User < ActiveRecord::Base
    has_many :user_emails
end

并覆盖devise的方法以在User模型中查找记录:

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  if email = conditions.delete(:email)
    User.includes(:user_emails).where('user_emails.email = ?', email).first
  else
    super(warden_conditions)
  end

在此处阅读有关覆盖的更多信息:https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

【讨论】:

  • 这对于其他 Devise 查找(例如通过确认令牌或解锁令牌查找用户)将失败(以潜在的不安全方式)。请参阅我的答案以进行修复。
  • 您如何处理密码恢复?如果我想让用户选择他希望将链接发送到哪个电子邮件,我该怎么办?
  • 据我所知,要重置密码,用户必须在表单中填写他的电子邮件。如果电子邮件存在,您将发送消息。
【解决方案2】:

Bob 的答案很接近,但它有一个潜在的危险错误。 find_first_by_auth_conditions 方法应如下所示:

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  if email = conditions.delete(:email)
    User.includes(:user_emails).where('user_emails.email = ?', email).first
  else
    super(warden_conditions)
  end
end

电子邮件检查和对super 的调用很重要,因为Devise 也使用此方法通过confirmation_tokenunlock_tokenreset_token 查找Users。如果没有 else 分支,对没有 email 参数的此方法的任何调用都将失败,或者使用 nil 电子邮件加载用户。

【讨论】:

  • 谢谢)更新了我的答案)
【解决方案3】:

我建议你创建一个新模型SecondaryEmail
一个User可以has_many :secondary_emails,每个SecondaryEmailbelongs_to :user

您必须为SecondaryEmail 中的每封电子邮件添加唯一性验证,此外,还必须确保没有新的 SecondaryEmail 已经是任何用户的主要电子邮件。
提供接口,以便User 可以通过这些验证添加他的secondary_emails。

下一步将覆盖 DeviseSessionController
在任何登录过程中,只要在用户的主要电子邮件中找不到电子邮件,就为SecondaryEmail.where(:email =&gt; params[:email]) 设置登录过程。如果存在,则使用该用户的密码进行身份验证,否则,用户不存在。

这是我到目前为止想出的。我真的很想知道专家对此的看法和方法。 :)

【讨论】:

    【解决方案4】:

    我不久前遇到了这个问题 - 并在 my blog 中概述了解决方案。

    步骤总结如下:

    • 电子邮件信息必须存储在另一个模型中,例如Email。所以User 有许多相关的Email 实例。
    • 我们很可能希望将一封电子邮件指定为可用于与用户交流的默认电子邮件。
    • Userfind_first_by_auth_conditions 的类方法用于查找用户提供的凭据 - 因此我们必须重写该方法才能使用 Email 模型进行搜索。
    • 我们将不得不更改默认视图,因为它们隐含地假定存在email 用户方法。我们可以使用为电子邮件添加代理访问器来委托用户的默认电子邮件,而不是完全重写视图。
    • 如果允许用户拥有多封电子邮件 - 我们还希望为用户提供在帐户编辑页面中添加/删除电子邮件的功能。
    • 如果您需要omniauth 集成,则必须修改设计wiki 中概述的User.from_omniauth 的库存实现以支持多个电子邮件。

    我的实现可用on Github

    【讨论】:

      【解决方案5】:

      这里给出的答案非常好,应该可以解决您的问题。要回答您的最后一个问题,我认为您不会为此找到宝石,因为即使它很常见,它也太简单了。只需按照建议从头开始,它应该不会做太多工作:)

      【讨论】:

        【解决方案6】:

        Bob 的回答在 rails 4.1.5 中为我抛出了一个 SQL 错误 - 下面的更改使它工作,每个 http://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-eager-loaded-associations

        def self.find_first_by_auth_conditions(warden_conditions)
          conditions = warden_conditions.dup
          if email = conditions.delete(:email)
            User.includes(:user_emails).where(user_emails: {email: email}).first
          else
            super(warden_conditions)
          end
        end
        

        【讨论】:

          【解决方案7】:

          您可以使用 devise-multi_email gem:https://github.com/allenwq/devise-multi_email

          devise :authenticatable 替换为devise :multi_email_authenticatable,这样您的模型可能如下所示:

          class User < ActiveRecord::Base
            has_many :emails
          
            # Replace :database_authenticatable, with :multi_email_authenticatable
            devise :multi_email_authenticatable, :registerable
          end
          
          class Email < ActiveRecord::Base
            belongs_to :user
          end
          

          如果您希望所有电子邮件都可以确认并从您的任何电子邮件中恢复您的密码,只需

          devise :multi_email_authenticatable, :multi_email_confirmable, :confirmable

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-08-30
            • 1970-01-01
            • 1970-01-01
            • 2017-03-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多