Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pre-populate my Rails 4 application with a Google user?

I’m using Rails 4.2.5 with the “omniauth-google-oauth2” gem. In my application, the only way users will be able to sign in is through their Google or Facebook logins. What I would like is to pre-populate my application with an initial user, me (email = ‘[email protected]”), with the admin role. It would be nice to do this programmatically so that when I roll this out to other environments I can use the same code.

My roles table (through db/seeds.rb) has the roles

Admin
User

and my app/model/user.rb file has

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

I’m not sure how to do what I want, however, and so would value some counsel.

like image 694
Dave Avatar asked Apr 28 '16 20:04

Dave


1 Answers

Now assume you have your Google uid. Just create a user from your seeds, e.g.:

user = User.new(
  provider: "google",
  uid: "your-google-id",
  email: "[email protected]",
  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

With that, when you log in with Google, the omniauth logic should be able to find the seed user, which means you'll be able to act as admin.

Please do note this assumes you won't need the Google oauth token to do any further operation as you don't have that saved, and from your from_omniauth it doesn't save if the user record exists already.

P.S. from your example code, Oauth info is saved directly to User model (provider and uid). With that, I'm afraid a user won't be able to log in with Facebook and Google at the same time as both would want to save to these two fields.

Update: pasting a model from my codebase that is a separate model from User which allows multiple providers login. Of course the controller needs to update to use Authorization instead of User. Just in case it helps.

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
like image 187
James Chen Avatar answered Sep 17 '22 19:09

James Chen