【问题标题】:How do I pre-populate my Rails 4 application with a Google user?如何使用 Google 用户预填充我的 Rails 4 应用程序?
【发布时间】:2016-04-28 20:00:10
【问题描述】:

我正在使用带有“omniauth-google-oauth2”gem 的 Rails 4.2.5。在我的应用程序中,用户能够登录的唯一方法是通过他们的 Google 或 Facebook 登录。我想要的是使用具有管理员角色的初始用户我(电子邮件 = 'davea@gmail.com')预先填充我的应用程序。以编程方式执行此操作会很好,这样当我将其推广到其他环境时,我可以使用相同的代码。

我的角色表(通过 db/seeds.rb)有角色

Admin
User

我的 app/model/user.rb 文件有

def self.from_omniauth(auth)
  where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
    user.provider = auth.provider
    user.uid = auth.uid
    user.name = auth.info.name
    user.oauth_token = auth.credentials.token
    user.oauth_expires_at = Time.at(auth.credentials.expires_at)
    user.save!
  end
end

但是,我不确定如何做我想做的事,因此我会重视一些建议。

【问题讨论】:

    标签: ruby-on-rails-4 omniauth seed


    【解决方案1】:

    现在假设您有 Google uid。只需从您的种子中创建一个用户,例如:

    user = User.new(
      provider: "google",
      uid: "your-google-id",
      email: "davea@gmail.com",
      name: "Your name"
    )
    user.roles << admin_role # Replace this line with your role assignment
    user.save # Perhaps use save(validate: false) if there're validations for other fields
    

    这样,当您使用 Google 登录时,omniauth 逻辑应该能够找到种子用户,这意味着您将能够充当管理员。

    请注意,这假设您不需要 Google oauth 令牌来执行任何进一步的操作,因为您没有保存该令牌,并且如果用户记录已经存在,则不会从您的 from_omniauth 保存。

    附:从您的示例代码中,Oauth 信息直接保存到 User 模型(provideruid)。这样一来,恐怕用户将无法同时使用 Facebook 和 Google 登录,因为两者都希望保存到这两个字段。

    更新:从我的代码库中粘贴一个模型,该模型与 User 不同,它允许多个提供商登录。当然控制器需要更新以使用Authorization 而不是User。以防万一。

    class Authorization < ActiveRecord::Base
      belongs_to :user
    
      def self.from_omniauth(auth)
        authorization = where(auth.slice(:provider, :uid)).first_or_create
        return authorization if authorization.user
    
        if user = User.where(email: auth.info.email).first
          authorization.bind_user(user)
        else
          user = authorization.create_user(auth.info)
        end
    
        authorization
      end
    
      def bind_user(user)
        self.user = user
        save
      end
    
      def create_user(info)
        user = User.new(
          email:      info.email,
          password:   Devise.friendly_token[0, 20],
          first_name: info.first_name,
          last_name:  info.last_name,
        )
        user.save(validate: false)
    
        bind_user(user)
    
        user
      end
    end
    

    【讨论】:

    • 嗨,如果用户不能同时登录 Google 和 Facebook 以及我的应用程序,那很好。我对您为什么将 self.from_omniauth 从 User 模型移到 Authorization 模型感到困惑。如果我的数据库已经包含与提供者和 uid 匹配的用户,那么是否不会创建重复的用户?
    • @Dave 是的,授权模型的目的是支持同一用户的多个提供者。没有它(从您的代码),当使用 Facebook 和 Google 登录时,将创建两次用户。这不是一个大问题,但是如果您还从提供商处检索电子邮件并将其存储到用户表中,同时将电子邮件作为登录标识符,则会导致问题。
    【解决方案2】:

    您必须通过您的控制器通过您的 seed.rb 文件运行请求才能执行 OAuth2 流程。

    由于您很可能需要输入凭据或从 GUI 中选择您的 google 帐户,因此我建议在您的 seed.rb 文件中运行系统命令,以打开浏览器访问您的授权操作的 url。

    # Mac:
    system("open <url_to_authorize_action>")
    

    如果这需要序列化,紧接着,添加一个 while 循环,每隔 N 次阈值检查一次数据库,以查看该用户是否被授权。

    while <user_not_authorized> do
        sleep <N seconds>
    end
    

    您可以将其应用于多个开发环境,但显然不能用于生产环境。

    【讨论】:

    • 我想做一些自动化的事情,不需要用户交互,也许除了运行一个文件。我可以利用我提前知道自己的 Google ID 的事实吗?
    猜你喜欢
    • 2018-06-22
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 2015-05-07
    • 2013-09-11
    相关资源
    最近更新 更多