Hi I'm building an api section for an app. My all api related controllers resides inside app/controllers/api directory.
My concern is that in application_controller there is a filter before_action
:authenticate_user!, so I have to be in login mode to access the api.
My current solution: I'm adding skip_before_action :authenticate_user! in all the controllers which are in
app/controllers/api directory..
Problem: I have to write in all the controllers and I have around 80 controllers
My expectation: Is there a way where I can write in application_controller itself something like this
before_action :authenticate_user!, except: [all the controllers which are in api directory]
You will have to specify skip_before_action :authenticate_user! in every controller whose actions aren't supposed to be authenticated. You can not pass the name of controller or any thing like that as an argument to skip_before_action method.
One solution is: You can make a controller called APIController, and you can specify the skip_before_action thing there like:
class APIController < ApplicationController
skip_before_action :authenticate_user!
# rest of the code
end
And then all the controllers at app/controllers/api/ can inherit from APIController.
class OtherController < APIController
end
You can try like this if all the controllers are under API folder:
class ApplicationController < ActionController::Base
before_action :authenticate!
def authenticate!
if params[:controller].split("/").first == "api"
return true # or put code for what wherever authenticate you use for api
else
authenticate_user!
end
end
end
Related
I have a rails 4.2.x app, with devise for authentication - I have several controllers.
I want the devise authenticate_user! method to be run on all controllers and actions except on the home controller index action. (Of course, authenticate_user! itself takes care that devise actions like login go through)
I can ensure that every controller action runs the before_action in application_controller.rb:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
...
end
I can also restrict a specific set of actions on all controllers:
class ApplicationController < ActionController::Base
before_action :authenticate_user!, except: [:index]
...
end
But I don't see how to make just home/index to be an exception.
I could, of course, manually add before_action :authenticate_user! to every controller, and add an exception to the home controller for the index action. But this is not very dry, and if I add new controllers, I need to remember to add this before_action to each of them.
What you have to do is to set autheticate_user! on all controllers like that :
class ApplicationController < ActionController::Base
before_action :authenticate_user!
...
end
And then on your HomeController you do that :
class HomeController < ApplicationController
skip_before_action :authenticate_user!, only: [:index]
...
end
Hope this will help you !
You can use params[:controller] to detect controller name of request.
class ApplicationController < ActionController::Base
before_action :authenticate_user!
AUTHENTICATE_USER_EXCEPT_CONTROLLERS = ['controller_names_you_want_to_exclude']
...
def authenticate_user!
unless AUTHENTICATE_USER_EXCEPT_CONTROLLERS.include?(params[:controller])
super
end
end
end
I am trying to require login on all pages on my Rails 4 web site.
In the ApplicationController I have added before_action :authenticate_user!, but it simply doesn't do anything. I have tried to add the same before_action :authenticate_user! to another controller, and it works fine.
Do I need to do something else to the ApplicationController, to make the login be required on all actions (Except signup/signin)?
Here's the actual code we use:
#app/controllers/application_controller.rb
Class ApplicationController < ActionController::Base
#Actions
before_action :authenticate_user! #-> routes to the login / signup if not authenticated
end
The problem you probably have is two-fold:
--
Make sure your other controllers are inheriting from application_controller:
#app/controllers/other_controller.rb
Class OtherController < ApplicationController
...
end
--
You're somehow "skipping" the before_action callback
If you're using skip_before_action anywhere, you need to remove it. It will likely cause a problem with your authenticate_user! method. To fix this, I would firstly test without any skip_before_action callbacks, and then see what gets it working correctly
A further note - signin / signup won't matter. They all inherit from the Devise controllers; they'll just run as required.
UPDATED 2019
In your routes.rb file you may have mentioned only authenticated_user path like below
authenticated :user do
root to: 'home#index', as: :root_app
end
You should mention unauthenticated_user path too to make it work or just root path without unauthenticated_user or authenticated_user
In Rails what is the before_filter syntax when you want to "except" controller "abc".
Example, in the application_controller if I want to say:
before_filter :login_required :except => ["-name of controller-"]
Background - Just wanted basic authentication across the whole app except the controller that actually handles getting a user authenticated....
You can put the following line in the controller where the before_filter should not be executed:
skip_before_filter :login_required
You can even specifiy the methods where the before_filter is ignored with :only and :except options:
skip_before_filter :login_required, :only => [:login]
An example here.
Edit: with Rails 4, before_filter is aliased with before_action, and skip_before_filter is also aliased with skip_before_action
The before_filter syntax is
before_filter :login_required, :except => ["-name of the action-"]
Have a look on Rails API Doc.
Instead of using the controller name, I'd recommend taking advantage of the fact that controllers inherit their filters from their parent. So what I'd recommend is something like this:
# app/controllers/application_controller.rb
class ApplicationController
# no filters here
end
# app/controllers/authenticated_controller.rb
class AuthenticatedController < ApplicationController
before_filter :login_required
end
# app/controllers/some_other_controller.rb
class SomeOtherController < AuthenticatedController
# inherits the before_filter from AuthenticatedController
# use this for most of your other controllers
end
# app/controllers/unauthenticated_controller.rb
class UnauthenticatedController < ApplicationController
# no filters, since this inherits directly from ApplicationController
# use this for the controller that you don't want to check login on
end
This means controllers know whether they're supposed to check login, rather than having a (possibly brittle) list of names.
I'm using devise for authentication and have some before_filters in my application controller. Issue I'm seeing is that when I try to logout the before_filter intercepts that and keeps me on the view that's I've setup in the before_filter. Is there any way for me to specify which controllers should be excluded from the application controller or some other file?
In the controller where you want to skip a before filter specified in an inherited controller, you can tell rails to skip the filter
class ApplicationController
before_filter :authenticate_user!
end
class SessionsController < ApplicationController
skip_before_filter :authenticate_user!
end
You can qualify a filter with :only or :except.
before_filter :filter_name, :except => [:action1, :action2]
Or if the filter (as I now see is the case in your situation) is defined in ApplicationController and you want to bypass it in a subclass controller, you can use a skip_before_filter with the same qualifications in the subclass controller:
skip_before_filter :filter_name, :except => [:action1, :action2]
In config/application.rb
config.to_prepare do
Devise::SessionsController.skip_before_filter :authenticate_user!
end
Referenced by:
How to skip a before_filter for Devise's SessionsController?
Answers above are good except:
DEPRECATION WARNING: skip_before_filter is deprecated and will be removed in Rails 5.1. Use skip_before_action instead.
So please use before_action and skip_before_action instead of *-filter.
In Ruby on Rails, I would like to add a before_filter to every controller except for one. Currently I have in ApplicationController:
before_filter :authenticate
Is there a way to apply this rule inside ApplicationController rather than adding before_filter :authenticate in every controller except the public controller?
If you want to run this filter in every controller but one, why not simply skip it?
class PublicController < ApplicationController
skip_before_filter :authenticate
end
If you want to skip a particular action, you can use :except:
before_filter :authenticate, :except => [ :index ]
Put the before filter in ApplicationController and then skip it in the controller where you don't want it:
skip_before_filter :authenticate