class UserSessionsController < ApplicationController
skip_before_action :require_login, except: [:destroy]
def new
...
end
def create
...
end
def destroy
logout
redirect_to signin_path , flash: { info: 'Bye!' }
end
end
class ApplicationController < ActionController::Base
before_action :require_login
private
def not_authenticated
redirect_to signin_path, flash: { danger: "ALARM!" }
end
end
After I logout, I'm redirected to sign in page with flash message "ALARM".
After that, when I log in again I'm redirected to sign in page with flash message "Bye!"
Please, help!
Ok, this was some kind of sorcery bug. You just need to skip require_login before destroy session too
Related
I am using the idiom described in https://guides.rubyonrails.org/v2.3/action_controller_overview.html#other-ways-to-use-filters
# /app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter do |controller|
redirect_to new_login_url unless controller.send(:logged_in?)
end
end
Now if the signing in process is successful, how
can I examine if it was, and b)
how can I re-redirect the user to the requested controller action?
How do I do this login-process via AJAX and JSON ?
EDIT: Also I get the following Error Message
uninitialized constant ApplicationController::LoginFilter
When I use the more elaborate solution suggested in 6.2 Other Ways to Use Filters instead of the one above such that my Controller looks like this
# /app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_return_path, LoginFilter
def set_return_path
return if devise_controller?
session['user_return_to'] = request.url unless current_user
end
class LoginFilter
def self.filter(controller)
unless controller.send(:logged_in?)
controller.flash[:error] = "You must be logged in"
controller.redirect_to controller.new_login_url
end
end
end
end
Thanks
von Spotz
You can add a before_action in the application_controller.rb where you save the requested page url:
class ApplicationController < ActionController::Base
before_action :set_return_path
def set_return_path
return if devise_controller?
session['user_return_to'] = request.url unless current_user
end
end
And then redirect the user to this url after the successful sign-in:
class SessionsController < Devise::SessionsController
def after_sign_in_path_for(resource)
return root_url if session['user_return_to'].blank?
session['user_return_to']
end
end
i have this routes:
Rails.application.routes.draw do
root 'login#new'
get '/home/inicio', to: 'home#index'
scope '/login' do
get '/acesso', to:'login#new'
post '/acessorecebendo', to:'login#create', as:'user'
get '/sair', to:'login#destroy'
end
resources :login
resources :home
resources :produtos
resources :fornecedors
end
the Login controller:
class LoginController < ApplicationController
protect_from_forgery
def new
if session[:user]
#user = User.find(session[:user])
end
end
def destroy
reset_session
redirect_to "/login/acesso", notice: "Você foi deslogado"
end
def create
user = User.validate(login_params[:email], login_params[:senha])
if user
session[:user] = user.id
redirect_to "/home/inicio", notice: "login feito com sucesso"
else
redirect_to "/login/acesso", notice: "Dados incorretos"
end
end
private
def login_params
params.require(:login).permit(:email, :senha)
end
end
The home controller:
class HomeController < ApplicationController protect_from_forgery with: :exception
def new
#user = User.find_by(id: session[:user]) end
def index
#produtos = Produto.all
render 'inicio' end
def show
if session[:user]
#user = User.find(session[:user])
end end end
I'm getting an error on the Home view (new.html.erb):
<header>
<h2>Bem-vindo <%= #user.nome %></h2>
<nav>
undefined method `nome' for nil:NilClass
Why i have some problems with the session? I can do the login and i wanna see the user informations of this session on the redirected page, like if i can pass the #user variable assigned on the login action to the home controller to use it.
This is happening because your #user is being set only in index and show, but you are trying to reference it from the new action.
Consider moving this logic to a before_action
class HomeController < ApplicationController
before_action if: ->{ session[:user] } do
#user = User.find_by(id: session[:user])
end
end
If this controller needs to assume that #user is present, you should also have a before_action that handles the case of a missing user account. I usually put this behavior into a AuthenticatedController class and inherit from it where needed.
User.find is not optimal here, because it will throw an exception if no record is found.
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 using Rails 3.2 and Authlogic. I have the following code:
class ApplicationController < ActionController::Base
private
def store_location
session[:return_to] = request.url
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
end
class UserSessionsController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => :destroy
def new
#user_session = UserSession.new
#header_title = "Login"
end
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:success] = "Login successful!"
redirect_back_or_default root_url
else
render 'new'
end
end
def destroy
current_user_session.destroy
flash[:success] = "Logout successful!"
redirect_back_or_default root_url
end
end
This code is quite generic. When we use the before_filter:
before_filter :require_user, :only => [:new, :edit, :update, :create]
It will automatically store_location and redirect us back to the proper page. However, how do I do this:
I'm in posts/1 which doesn't require_user.
I click the login link on my top navigation bar.
It shows the login page.
Once login, I will be redirected back to posts/1 instead of the root_url.
Place a direct call to store_location in the sessions controller new action.
# user_sessions_controller.rb
def new
store_location if session[:return_to].blank?
#user_session = UserSession.new
#header_title = "Login"
end
This will first check for an existing return_to pair in the sessions hash. You don't want to overwrite it in case, for example, a user is redirected to the new action because of a bad password.
This will also skip store_location if it was already called from require_user.
After a successful redirect, you have to delete the return_to pair from the sessions hash; setting it to nil is not enough:
# application_controller.rb
def redirect_back_or_default(default)
redirect_to(session.delete(:return_to) || default)
end
I added a store_referrer_location to make it work:
# application_controller.rb
class ApplicationController < ActionController::Base
private
def store_referrer_location
session[:return_to] = request.referrer
end
end
# user_sessions_controller.rb
class UserSessionsController < ApplicationController
def new
store_referrer_location if session[:return_to].blank?
#user_session = UserSession.new
#header_title = "Login"
end
...
def destroy
store_referrer_location if session[:return_to].blank?
current_user_session.destroy
flash[:success] = "Logout successful!"
redirect_back_or_default root_url
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.