On My current app that i'm developing, i can sign up using Facebook and Google+. But when I added the ability for signing up with just a regular email, i got this error, I'll appreciate some help please ...
Here are some of my code
#SessionsController
def create
#user = User.from_omniauth(env["omniauth.auth"])
# session[:user_id] = #user.id
# redirect_to root_path
#user = User.find_by_email params[:email]
if #user && #user.authenticate(params[:password])
session[:user_id] = #user.id
redirect_to root_path
else
flash[:alert] = "Wrong email or password"
render :new
end
end
#user.rb
class User < ActiveRecord::Base
has_secure_password
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.image = auth.info.image
user.gender = auth.extra.raw_info.gender
user.location = auth.extra.raw_info.location.name
user.location = auth.extra.raw_info.locale
# user.url = auth_hash['info']['urls'][user.provider.capitalize]
user.save
end
end
So When attempting to signUp with using the email, here's what happen !
enter image description here
I'm guessing that error coming because i'm calling from_omniauth and i'm not passing a provider, which i don't need to use in this case.
You might consider starting fresh - using https://github.com/plataformatec/devise and then adding OmniAuth on top of this (https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview).
Related
I'm getting the error: "couldn't find user with id" when trying to sign in with facebook. I want it where if a user is had already been created it triggers the first set of code in the conditional and if the user is new it triggers the second set of code:
sessions_controller
def facebook
preexisting_user = User.find(params[:id]) # What should go in this line?
user = User.from_omniauth(env["omniauth.auth"])
if preexisting_user
cookies.permanent.signed[:user_id] = user.id
redirect_to root_url
flash.now[:info] = 'Welcome Back to Live to Challenge!'
else
action = session.delete(:challenge_action)
user.challenges.create(action: action)
user.send_welcome_email
user.remember
cookies.permanent.signed[:user_id] = user.id
redirect_to tutorial_url
flash.now[:info] = 'Welcome to Live to Challenge!'
end
end
user.rb
def self.from_omniauth(auth)
# Sets 60 day auth token
oauth = Koala::Facebook::OAuth.new("154037ewr2976229929", "ee917abf2ere8f1c98274cdfwqreaebb1346f4")
new_access_info = oauth.exchange_access_token_info auth.credentials.token
new_access_token = new_access_info["access_token"]
new_access_expires_at = DateTime.now + new_access_info["expires"].to_i.seconds
where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
user.provider = auth.provider
user.image = auth.info.image
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = new_access_token # auth.credentials.token <- your old token. Not needed anymore.
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.password = (0...8).map { (65 + rand(26)).chr }.join
user.email = SecureRandom.hex + "#mailinator.com" unless user.email.present?
user.activated = true
user.save!
end
end
You can try below code, i am sure it will work.
def facebook
user = User.from_omniauth(env["omniauth.auth"])
# preexisting_user = User.find(params[:id]) # What should go in this line?
# user.persisted? is what you need to add if you want to add here
# if user pre existed, it will execute if block otherwise else block.
# checks if pre-existing user
if user.persisted?
cookies.permanent.signed[:user_id] = user.id
redirect_to root_url
flash.now[:info] = 'Welcome Back to Live to Challenge!'
else
action = session.delete(:challenge_action)
user.challenges.create(action: action)
user.send_welcome_email
user.remember
cookies.permanent.signed[:user_id] = user.id
redirect_to tutorial_url
flash.now[:info] = 'Welcome to Live to Challenge!'
end
end
Approach #1
Send email reminder to <%= email_field_tag :email, nil, placeholder: 'Enter Email', class: "send-email" %> # :email belongs to the users table
Approach #2
Send email reminder to <%= f.email_field :default_email, class: "send-email", placeholder: "Enter Email" %> # :default_email belongs to the challenges table. The point of this is to try something in the create process like current_user.email == #challenge.default_email
The user is then redirected to signup url
If a user signs up via Facebook a random email is generated so that he can get through the validation process: user.email = SecureRandom.hex + "#mailinator.com"
user.rb
def self.from_omniauth(auth)
# Sets 60 day auth token
oauth = Koala::Facebook::OAuth.new("125402372971231236229929", "ee917abf2e8f1c98274cdafssadffddffaebb1346f4")
new_access_info = oauth.exchange_access_token_info auth.credentials.token
new_access_token = new_access_info["access_token"]
new_access_expires_at = DateTime.now + new_access_info["expires"].to_i.seconds
where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
user.provider = auth.provider
user.image = auth.info.image
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = new_access_token # auth.credentials.token <- your old token. Not needed anymore.
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.password = (0...8).map { (65 + rand(26)).chr }.join
user.email = SecureRandom.hex + "#mailinator.com" unless user.email.present?
user.activated = true
user.save!
end
end
But how can we make the email the user inputted in the challenges/create.html.erb form seen above override the SecureRandom email?
users_controller
def create
#user = User.new(user_params)
if #user.save
action = session.delete(:challenge_action)
deadline = session.delete(:challenge_deadline)
committed = session.delete(:challenge_committed)
date_started = session.delete(:challenge_date_started)
order = session.delete(:challenge_order)
days_challenged = session.delete(:challenge_days_challenged)
why = session.delete(:challenge_why)
conceal = session.delete(:challenge_conceal)
#user.challenges.create(action: action, deadline: deadline, why: why, conceal: conceal, date_started: date_started, committed: committed, days_challenged: days_challenged)
end
redirect_to root_url
else
render 'new'
end
end
challenges_controller
before_action :update_user_email, if: proc {|c| c.current_user.present? && c.params[:email].present? }
def create
#challenge = Challenge.new(challenge_params)
if params[:step] == '2'
if current_user == nil
# If there is no user, store values to the session.
session[:challenge_action] = challenge_params[:action]
session[:challenge_committed] = challenge_params[:committed]
session[:challenge_deadline] = [params["challenge"]["deadline(3i)"], params["challenge"]["deadline(2i)"], params["challenge"]["deadline(1i)"]].join('/')
session[:challenge_date_started] = [params["challenge"]["date_started(3i)"], params["challenge"]["date_started(2i)"], params["challenge"]["date_started(1i)"]].join('/')
session[:challenge_order] = challenge_params[:order]
session[:challenge_days_challenged] = challenge_params[:days_challenged]
session[:challenge_why] = challenge_params[:why]
session[:challenge_conceal] = challenge_params[:conceal]
redirect_to signup_path
else
#challenge = current_user.challenges.build(challenge_params)
#challenge.save
redirect_to root_path
end
else
respond_modal_with #challenge
end
end
private
def update_user_email
email = params[:email]
current_user.update_attribute(:email, email)
end
sessions_controller
class SessionsController < ApplicationController
def new
end
def facebook
user = User.from_omniauth(env["omniauth.auth"])
user.remember
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:remember_token] = user.remember_token
redirect_to root_url
end
def create
assign_email(cookies[:challenges_email])
user = User.find_by(email: params[:session][:email].downcase)
assign_email(cookies[:challenges_email])
if user && user.authenticate(params[:session][:password])
assign_email(cookies[:challenges_email])
log_in user
params[:session][:remember_me] == 'nil' ? forget(user) : remember(user)
redirect_to root_url
else
flash.now[:info] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
log_out if logged_in?
redirect_to root_url
end
end
We talked about setting it as a cookie in another question. If you're taking that approach, you could pass the cookie to a method. Something like what is discussed in this question:
before_create :set_user_email
def assign_email(email)
#email = email
end
def set_user_email
self.email = #email
end
then in the controller action where you have access to the cookie:
assign_email(cookies[:challenge_email])
#joseph had answered it pretty simple but i think you can just get email in the field by setting it in the controller like;
User.new(:email => "email you want to show in the field")
no need to pass nil user object pass a new object.
And in the view file it will shown in email field with
Send email reminder to <%= f.email_field :email, class: "send-email", placeholder: "Enter Email" %>
How to use ActiveRecord::Base.transaction after first_or_create ?
here is my model method:
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.password = 'password'
user.password_confirmation = 'password'
user.crypted_password = 'password'
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
In my controller:
def social_login
#user = User.from_omniauth(env["omniauth.auth"])
ActiveRecord::Base.transaction do
add_sites(#user)
#user.mobile = mobile_view?
#user.addresses.last.email = #user.email
add_point_to_customer(#user)
#user.add_mail_subscription_if_doesnt_exist(active_site)
end
end
Here is my controller
def social_login
user = User.from_omniauth(env["omniauth.auth"])
session_params = user.attributes.merge("email" => user.email, "password" => user.crypted_password)
#user_session ||= UserSession.new(session_params, true)
if #user_session.save
user = User.where(email: #user_session.email).first
redirect_to root_path, :notice => "Signed in succesfully from #{env["omniauth.auth"].provider.titleize}. Greetings #{user.name.titleize} ;)"
else
flash.now[:alert] = "Sign in failed."
render "new"
end
end
here is the model to handle the omniauth process
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.password = auth.credentials.token
user.password_confirmation = auth.credentials.token
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
I always getting error when trying to save the session. It says:
Authlogic::Session::Existence::SessionInvalidError: Your session is invalid and has the following errors: Email is not valid
can you guys help me? thanks
Did you enable the email permission in your facebook app config/rails's initializion?
Like this:
config.omniauth :facebook, "APP_ID", "APP_SECRET", {:scope => 'email,...'}
I am working on rails 3 and using the koala gem to get a connection to the facebook graph api.
And I am using omniauth to autenticate users.
So when a new user logs to the site, the session_controller handles the new user:
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env['omniauth.auth'])
session[:user_id] = user.id
redirect_to root_url, notice: "Signed in!"
end
The create method call the "from_omniauth" class metod in the User.rb model, to create a new user:
class User < ActiveRecord::Base
has_many :friends
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.first_name = auth["info"]["first_name"]
user.last_name = auth["info"]["last_name"]
user.image = auth["info"]["image"]
user.email = auth["info"]["email"]
user.gender = auth["extra"]["raw_info"]["gender"]
user.location = auth["extra"]["raw_info"]["location"]["name"]
user.token = auth["credentials"]["token"]
end
user.save!
end
I would like to save user facebook friends also and store it in a separate tabel called friends, so I made this friend model:
class Friend < ActiveRecord::Base
attr_accessible :name
belongs_to :user
validates :user_id, presence: true
def facebook
#Facebook ||= Koala::Facebook::API.new(token)
end
def add_friends
facebook { |fb| fb.get_connection("me", "friends") }
end
end
But I am lost on how to store users friends, I whould like to know:
How I can create a user, and store it friends
Where should I call the add_friends method?
fb.get_connection("me", "friends") return a array of hashes, like this > [{"name"=>"Johan Gyllenspetz", "id"=>"3624556"}, {"name"=>"Gustaf Josefsson", . And I would like to store the name and uid.
This is how I'd do this:
class User < ActiveRecord::Base
has_many :friends
def self.from_omniauth(auth)
user = 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.first_name = auth["info"]["first_name"]
user.last_name = auth["info"]["last_name"]
user.image = auth["info"]["image"]
user.email = auth["info"]["email"]
user.gender = auth["extra"]["raw_info"]["gender"]
user.location = auth["extra"]["raw_info"]["location"]["name"]
user.token = auth["credentials"]["token"]
end
user.add_friends
user.save
user
end
def add_friends
#facebook.get_connection("me", "friends").each do |hash|
self.friends.where(:name => hash['name'], :uid => hash['id']).first_or_create
end
end
private
def facebook
#facebook ||= Koala::Facebook::API.new(token)
end
end