My user model has birthday and I'm trying to redirect to the edit page if it is blank after signing in with Facebook. I tried overriding the after_sign_in_path for resource but keep getting this error:
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
My Application controller:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def after_sign_in_path_for(resource)
stored_location_for(resource) ||
if resource.birthday.blank?
redirect_to edit_user_path(resource)
end
super
end
end
and my Omniauth controller:
class OmniauthCallbacksController < ApplicationController
skip_before_filter :authenticate_user!
def provides_callback_for
user = User.from_omniauth(env["omniauth.auth"], current_user)
if user.persisted?
flash[:notice] = "You have signed in!"
sign_in_and_redirect(user)
else
session['devise.user_attributed'] = user.attributes
redirect_to new_user_registration_url
end
end
def failure
flash[:notice] = "Something went wrong!"
redirect_to root_path
end
alias_method :facebook, :provides_callback_for
end
This should do the trick:
def after_sign_in_path_for(resource)
if resource.birthday.blank?
edit_user_registration_url
else
super
end
end
Related
I am implementing omniauth for twitter and I have run into an error "Couldn't find User with 'id'=true" the error is pointing to the application controller current_user metho. Heere is my current_user method:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_user
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
and here is my User model:
class User < ActiveRecord::Base
def self.find_or_create_by_auth(auth_data)
user = where(provider: auth_data[:provider], uid: auth_data[:uid]).first_or_create
user.update(name: auth_data[:info][:name])
end
end
and finally the SessionController is below:
class SessionsController < ApplicationController
def create
#user = User.find_or_create_by_auth(request.env["omniauth.auth"])
session[:user_id] = #user
redirect_to products_path, notice: "logged in as "
end
def destroy
session[:user_id] = nil
redirect_to root_path, notice: "Goodbye!!"
end
end
When I trying to log in the error pops and i can't get past login to load my index page.
I think your problem should be solved with following modification in User.find_or_create_by_auth method:
def self.find_or_create_by_auth(auth_data)
# all previous code
# you should return user from here
# your current code returned true of false
user
end
Also you should save #user.id in session, not full #user object:
session[:user_id] = #user.id
I finally solved this, the issue was that i had deleted the previous authenticated twitter user in the db and i was trying to authenticate with the same credentials again on the app.
so what i did is create a new twitter app and use different keys to authenticate into my rails App... hoep this explains it thanks
Problems with Devise!
I've been messing with it all weekend to no avail, maybe one of you guys know what's up.
I can successfully create and sign in with a user returning a 201 and the all the proper stuff (user_token and email_token), however any requests after the sign_in are rejected with a 401.
#app/controllers/application_controller.rb
class ApplicationController < ActionController::API
include ActionController::MimeResponds
include ActionController::HttpAuthentication::Token::ControllerMethods
include AuthenticatorHelper
# # Prevent CSRF attacks by raising an exception.
# # For APIs, you may want to use :null_session instead.
# protect_from_forgery with: :exception
helper_method :after_actions
# Use Devise to authenticate user before every action
before_filter :authenticate_user!
private
def id_filters
p = params.permit(ids:[])
return nil if p.blank?
p[:ids].map {|x| x.to_i}
end
end
The code enters the authenticate user action and then stops working. The helper I have included is this:
# Authenticates users by their authentication token and email if present.
# https://github.com/simplabs/ember-simple-auth/tree/master/packages/ember-simple-auth-devise#user-content-server-side-setup
module AuthenticatorHelper
def self.included(base)
unless base.instance_of? Module
base.prepend_before_filter :authenticate_user_from_token!
end
end
def authenticate_user_from_token!
authenticate_with_http_token do |token, options|
user_email = options[:user_email].presence
user = user_email && User.find_by_email(user_email)
if user && Devise.secure_compare(user.authentication_token, token)
sign_in user, store: false
end
end
end
end
The Ember Application that sits above my Rails App is sending over the proper headers each time: Token user_token="FEHR4ZpTGzsUSFvyzyKv", user_email="taylor#yolo.com" and was not changed when I updated Rails.
Another weird thing I noticed when I entered the debugger is the before_ filter :authenticate_user is executed before the sign_in my SessionsController. And here is the code for that Controller
#app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
def create
respond_to do |format|
format.html { super }
format.json do
self.resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
data = {
user_token: self.resource.authentication_token,
user_email: self.resource.email
}
render json: data, status: 201
end
end
end
end
Does anyone have any ideas as to what changes to Rails could have caused this problem? Any hunches? Could something else have caused the issue? Any guesses would be greatly appreciated! Thanks in advance for any help on the issue, and let me know if I you want to see any more code!
I am rolling R Bates authentication from scratch from here, and I'm wanting to put the call to the authorize method in the application controller. Basically I want the entire app locked down. Here is the app controller...
class ApplicationController < ActionController::Base
before_filter :authorize
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
def authorize
redirect_to login_url, alert: "Not authorized" if current_user.nil?
end
end
But the probably is I'm getting an infinite loop in my URL call. How should I hand this?
sessions controller
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_url, notice: "Logged in!"
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "Logged out!"
end
end
You can skip before_filter (like in #vee answer) for some actions of SessionsController:
skip_before_filter :authorize, only: [:new, :create]
Alternatively you can modify authorize method to avoid redirects in some cases:
def authorize
return if skip_authorization?("#{controller_name}##{action_name}")
redirect_to login_url, alert: "Not authorized" if current_user.nil?
end
def skip_authorization?(location)
%w(sessions#new sessions#create).include?(location)
end
The loop is because of the redirect_to login_url....
You should skip the authorize filter in controller that has the login action defined as:
class SessionsController < ApplicationController
skip_before_filter :authorize, only: :login
def login
...
end
...
end
Or to skip authorize filter for all actions, use skip_before_filter :authenticate without the only option.
I'm getting this error when a user tries to vote without first being signed-in:
undefined method `vote_for' for nil:NilClass
I have a regular "Post" scaffold and the users are voting on posts. How do I insert a command that redirects them to the user_sign_in if they're not already logged in?
class PostsController < InheritedResources::Base
def vote_up
begin
current_user.vote_for(#post = Post.find(params[:id]))
redirect_to [#post]
flash[:success] = "You have voted successfully"
rescue ActiveRecord::RecordInvalid
redirect_to [#post]
flash[:error] = "You have already voted"
end
end
end
Add a before_filter :authenticate_user! in your PostController. In the authenticate_user! method check the user session, and if the user is not signed in redirect to sign_in path.
Edit: As you already have Devise adding the before_filter should take care of the redirection to sign in path if the user is not signed in. The following will only work for vote_up action, if you'd like the same behavior for all the actions then you can replace the line with before_filter :authenticate_user!
class PostsController < InheritedResources::Base
# Add before_filter here and devise should handle the redirection if the user is not signed in.
before_filter :authenticate_user!, only: [:vote_up]
def vote_up
begin
current_user.vote_for(#post = Post.find(params[:id]))
redirect_to [#post]
flash[:success] = "You have voted successfully"
rescue ActiveRecord::RecordInvalid
redirect_to [#post]
flash[:error] = "You have already voted"
end
end
end
I'm using devise and trying the next following:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :is_worker
def is_worker
if user_signed_in?
#email = current_user.email
if #email && Worker.find_by_email(#email).nil?
redirect_to '/tasksadmins'
else
redirect_to '/workers'
end
else
redirect_to '/users/sign_in'
end
end
end
when I try to enter the site: localhost:3000/tasksadmins, I got:
Oops! It was not possible to show this website
The website at http://localhost:3000/tasksadmins seems to be unavailable. The precise error was:
Too many redirects
It could be temporarily switched off or moved to a new address. Don't forget to check that your internet connection is working correctly.
How can I fix it please?
before_filter is applied to every single request. That's why it's redirecting again and again.
You might want to only filter specific actions:
before_filter :is_worker, only: :index
Another solution would be to check wether a redirect is necessary in #is_worker:
redirect_to '/workers' unless request.fullpath == '/workers'
EDIT:
Another way would be to skip the before filter for the target actions of your redirects. Example:
class WorkersController < ApplicationController
skip_before_filter :is_worker, only: :index
# …
end
In my case:
users_controller.rb
before_action :logged_in?, only: :new
def new
#user = User.new
render layout: "session"
end
and
application_controller.rb
def logged_in?
redirect_to users_new_url unless current_user.present?
end
When I was trying to redirect to the 'users/new' page,same error occurred.
This is just because I'm trying to redirect to the 'users/new' page and "def logged_in?" is also redirecting to the same page.
Then I changed the application_controller.rb code like this:
def logged_in?
redirect_to root_url unless current_user.blank?
end
Error_Resolved.