I wan't to use the before_action in application_controller.rb
and then some skip_before_actions ...
bit the defined function is not called ...
application_controller.rb
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
layout "application"
before_action :user_logged_in, :set_locale
private
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
# Prüft ob ein Nutzer eingeloggt ist.
def user_logged_in
puts "HA"
if session[:user_id].nil?
flash[:error] = "error"
redirect_to :controller => :startsites, :action => :index
else
flash[:error] = "ok"
redirect_to :controller => :startsites, :action => :index
end
end
end
The puts "HA" in user_logged_in is not shown ...
and in some controllers I tried to use this:
class MoviesController < ActionController::Base
skip_before_action :user_logged_in, only: [:index, :show]
also not working ... why?
Where are you looking for the puts? If you were to call the Rails logger instead, it would work.
Try to insert a binding.pry instead of the puts and see what happens (you obviously need to have pry installed on your machine)
Related
I want to use the before_action in application_controller.rb and then some skip_before_actions to prevent some sites from being called before a user is logged in.
But the defined function in my application_controller.erb is not called ...
application_controller.erb
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
layout "application"
before_action :user_logged_in, :set_locale
private
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
# Prüft ob ein Nutzer eingeloggt ist.
def user_logged_in
puts "HA"
if session[:user_id].nil?
flash[:error] = "error"
redirect_to :controller => :startsites, :action => :index
else
flash[:error] = "ok"
redirect_to :controller => :startsites, :action => :index
end
end
end
The puts "HA" in user_logged_in is not printed in my server console. So I think the function is not called yet .. but why?
And in some controllers I tried to use this:
class MoviesController < ActionController::Base
skip_before_action :user_logged_in, only: [:index, :show]
also not working ... why?
Thank you very much for your help.
You are trying to call through ActionController. Its not possible that way, as you built it.
ActionController::Base
-ApplicationController #your method in this controller
ActionController::Base
-MoviesController #yr trying to skip it right here
To skip it, you have to inherit like below:
ActionController::Base
-ApplicationController #yr method is here
--MoviesController #it will find that method and skip it.
Controllers
# application_controller.rb
class ApplicationController < ActionController::Base
end
# movies_controller.rb
class MoviesController < ApplicationController
end
I have defined my own method authorize_user in one of my controllers, as:
def authorize_user
if !((current_user.has_role? :admin, #operator) || (current_user.has_role? :super_admin))
raise CanCan::AccessDenied
end
end
I want to rescue from the CanCan exception (or any other exception for that matter). I have used Rolify in my app. How do I rescue and redirect to the root_url of my app with a custom message?
I have tried the following options, but none of them worked:
Try 1:
rescue CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
Error in this case: syntax error, unexpected keyword_do, expecting '('
Try 2:
rescue CanCan::AccessDenied
redirect_to root_url, :alert => "Unauthorized Access"
Error in this case: Render and/or redirect were called multiple times in this action
How do I solve this issue?
This is my controller code:
class CabsController < ApplicationController
before_action :set_cab, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
after_action :authorize_user
# Some basic CRUD actions
private
def set_cab
#cab = Cab.find(params[:id])
#operator = Operator.find(params[:operator_id])
end
def cab_params
params.require(:cab).permit(:category, :number)
end
def authorize_user
if !((current_user.has_role? :admin, #operator) || (current_user.has_role? :super_admin))
raise CanCan::AccessDenied
end
end
end
I think you could try the rescue_from method.
For example, your ApplicationController, would look like this:
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied, with: :not_authorized
#other stuff
private
def not_authorized
redirect_to root_url, alert: "Unauthorized Access"
end
end
Since the question was updated with more code, here is additional information:
Some suggestions:
Make the :authorize_user a before_action as well. That way you don't need to worry about code running in the action even when the user was not allowed to do stuff.
You might also need to add the same :only option as for the :set_cab since you use the #operator instance variable.
Last, a personal code style preference is that I would have changed the if ! to unless to increase reading flow.
Try redirect_to(...) and return.
Agreeing with Jakob W I would like to point, that authorization (and authentication) MUST be performed only before action. What is the purpose of any authorization and exception raising when DB transaction, reading/writing to filesystem etc have been already done?
And using before_action has no problem with Render and/or redirect were called multiple times in this action - there will be only one redirect - in exception handling before controller method call.
So, I recommend next code (updated Jakob W's sample):
class CabsController < ApplicationController
#...
before_action :authorize_user
private
#...
def authorize_user
if !((current_user.has_role? :admin, #operator) || (current_user.has_role? :super_admin))
raise CanCan::AccessDenied
end
end
end
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied, with: :not_authorized
#other stuff
private
def not_authorized
redirect_to(request.referrer || root_path), alert: "Unauthorized Access"
end
end
Could I recommend another authorization gem? I think this one is flexible and easy to use - pundit (https://github.com/elabs/pundit). Page on github has some useful tips on authorization.
Am using Devise for authentication and cancancan for authorization.Now i want to not allow the view user for some pages. So i add following codes. But it throws undefined local variable or method `current_user' for # error.
My ability.rb
class Ability
include CanCan::Ability
def initialize(dashboard_user)
current_dashboard_user ||= DashboardUser.new
if current_dashboard_user.CD_DASHBOARD_ADMIN?
can :manage, :all
else
can :read, :summary
can :read, :home
end
.........
end
Application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :authenticate_dashboard_user!
protected
rescue_from CanCan::AccessDenied do |exception|
redirect_to main_app.root_url, :alert => exception.message
end
....
end
dashboard_user_controller.rb
class DashboardUsersController < ApplicationController
before_action :set_dashboard_user, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource
....
end
Okey, just do this trick for now. Somehow the current_user helper method is being called. So the quickest solution would be if you can do the following.
In your application_controller.rb file put this block:
def current_user
current_dashboard_user
end
# method_alias :current_user=, current_user # you may need this line if required.
helper_method: :current_user
I hope this will help.
i've some problem with the skip_before action:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :require_login
before_action :inc_cookies
def inc_cookies
if cookies[:token] != nil
#name = cookies[:name]
#surname = cookies[:surname]
#user_roomate = cookies[:roomate]
end
end
def require_login
if cookies[:token] == nil
puts "No token"
redirect_to '/'
end
end
end
and my other controller:
class UsersController < ApplicationController
skip_before_action :require_login, :except => [:landing, :connect, :create]
end
I don't know why, but when I'm on the root (the :landing action from UsersController), Rails try to pass in the require_login...
I've misundertood something with this filter, or do I something wrong?
Thanks for any help!
This sounds normal to me - you've asked rails to skip your before action, except if the action is :landing, :connect or :create whereas it sounds as though you want the opposite. If you want those 3 actions not to execute the require_login then you should be doing
skip_before_action :require_login, :only => [:landing, :connect, :create]
In my multilingual Rails app I have a ProfilesController. I am using a GET variable section to split the view into different tabs. I am also storing that variable in a session, so that it will be remembered across requests.
class ProfilesController < ApplicationController
before_action :signed_in_user
before_action :find_profile
before_action :set_section, :only => [:show, :edit]
def show
end
def edit
end
def update
if #profile.update_attributes(profile_params)
flash[:success] = t('profiles.flash_messages.profile_updated')
redirect_to edit_profile_path(:section => session[:section])
else
#title = t("views.#{session[:section]}")
render :edit
end
end
private
def find_profile
#profile = current_user.profile
end
def set_section
section = Profile::SECTIONS.include?(params[:section]) ? params[:section] : Profile::SECTIONS[0]
session[:section] = section
end
What I don't understand is why my update action constantly redirects to the default_locale rather than the locale the user chose and therefore stored in the session.
Can anybody tell me what I am missing here?
This is an excerpt of my routes.rb file: (Please note that I am using a singular resource here since each user can have only one profile)
MyApp::Application.routes.draw do
scope '(:locale)' do
resource :membership
...
get 'change_locale', :to => 'locales#change_locale'
end
end
Update:
class ApplicationController < ActionController::Base
before_action :set_locale
protected
def set_locale
if params[:locale]
if I18n.available_locales.include?(params[:locale].to_sym)
I18n.locale = session[:locale] || params[:locale] || I18n.default_locale
end
end
end
def default_url_options
{ :locale => I18n.locale }
end
end
Try to use:
redirect_to edit_profile_path(:section => session[:section], :locale => I18n.locale)
or
class ApplicationController < ActionController::Base
before_action :set_locale
def default_url_options(options={})
{ locale: I18n.locale }
end
protected
def set_locale
I18n.locale = (session[:locale] || params[:locale]).to_s.downcase.presence || I18n.default_locale
end
end
this will help.
I think you forgot to set default_url_options:
# app/controllers/application_controller.rb
def default_url_options(options={})
{ :locale => ((I18n.locale == I18n.default_locale) ? nil : I18n.locale) }
end