Restrict certain routes to logged in users - ruby-on-rails

I'd like /something to only be accessible for logged in users, I have a current_user helper which returns a user id or nil if the current visitor is not logged in.
Where would be the best place to limit access to /something in the controller or can it be added as part of the routes?

You must add in controller :before_filter and create action for that.
:before_filter :authenticate
def authenticate
redirect_to(registration_path) unless current_user.nil?
end
Also you can use :only or :except filter options.
Or i did not understant question?

You should handle that in your controller. Routes decide where things go and then it is up to the controller to decide if you're allowed to go there.
You should have a general purpose authenticate method in your ApplicationController that checks if someone is logged in and redirects them to a login page if they're not. Then in your specific controller:
class SomethingController < ApplicationController
before_filter :authenticate
def handler
#...
end
end
You can skip authentication for a specific handling with the :except option:
before_filter :authenticate, :except => [ :this_one, :and_this_one ]
There are other options as well, see the filters section of the Action Controller Overview for details.

Related

How to share conditional redirect logic for multiple routes in Rails?

I'm using Devise for authentication in a Rails 6 app. Once a user logs in, I'd like to conditionally check that they have completed onboarding before allowing them to visit any and all authenticated routes. If they haven't, then they should be redirected back through the onboarding flow. Something like this:
unless current_user.has_completed_onboarding
redirect_to '/onboarding'
end
I have about a dozen routes where I want to implement this logic. What's the best way to add this check before each request to an authenticated route without duplicating it within each controller? Thanks!
what you can do in this type of case is write a method in the ApplicationController. Suppose check_user_onboarding
def check_user_onboarding
return redirect_to '/onboarding' unless current_user.has_completed_onboarding
end
Then in the controllers you can check by adding a before_action callback. The below one will check all the methods of that controller.
before_action :check_user_onboarding
You can also specify the methods that needs to be checked like -
before_action :check_user_onboarding, only: [:method1, :method2]
or there is also except
before_action :check_user_onboarding, except: [:method1, :method2]

Ruby - Automatically running helper method

I have a login page saving a session to allow users to navigate subsequent pages. If you're not logged, I want to redirect you to the log in page. I have a SessionsHelper method for checking if the user is logged in and then if not, redirecting them back to the login page, But I don't want to have to call this in every controller action. Is there a way to easily run this method globally?
Traditionally this is done via a before_action filter. Something along these lines:
class ApplicationController
before_action :require_current_user
def require_current_user
redirect_to login_path unless current_user
end
end
class SessionsController < ApplicationController
# do not cause endless redirect loop
skip_before_action :require_current_user, only: [:new, :create]
end
Also, helpers are for simplifying views (currency formatting, styling, etc.). They are not to be used for this kind of functionality (session management, in this case).

Check if user_signed_in before run the special def in Rails

For example I have defs: def index, def manage, def new. And in routes I have the next:
if user_signed_in?
def new
end
end
But when I wrote it other def(index and manage) also asks me login. How can I do that just new def asks me login?
routes:
get "/new" => "posts#new"
Try adding this line to the controller instead
before_filter :authenticate_user!, only: [:new]
If you are indeed using Devise please skim the guide in its entirety.The filters are what you missed.
before_filter :authenticate_user! is the way to go.
What you are doing in your question is conditionally defining the controller's actions based on a boolean of whether a user is signed in/not, which is, in essence, a wrong approach. Besides, at the point of definition of the controller class, there isn't a user.

Require authorization active_admin/devise in controller :only index show edit destroy

I am trying to require an authorization in my controller called purcahses_controller.rb It's just an order form model with Show Edit Destroy.. I can view it in active_admin, the url being localhost/admin/purchases. But the problem is I can also view it at localhost/purchases. It lists all of the orders and allows all functions. Id like to route_to rooturl with a simple unauthorized message if the user isn't logged in.
You can do the following and it will give you option to redirect to any path you see fit.
In the file
config/initializers/active_admin.rb
Make the following change
config.authentication_method = :authenticate_active_admin_user!
Then inside your application controller adding something like this:
class ApplicationController < ActionController::Base
protect_from_forgery
def authenticate_active_admin_user!
authenticate_user!
unless current_user.superadmin?
flash[:alert] = "Unauthorized Access!"
redirect_to "/admin/login"
end
end
end
In your purchases_controller add the following before_filter line:
before_filter :authenticate_active_admin_user!
Hopefully this helps!
~Kevin
authenticate_active_admin_user gives you access to the admin authenticate user which will lead you to the authorization regardless of what you call in admin.
controller do
skip_before_action :authenticate_active_admin_user, only: :action
end
https://www.rubydoc.info/gems/nsm-activeadmin/0.2.2/ActiveAdmin%2FResourceController%3Aauthenticate_active_admin_user
https://github.com/activeadmin/activeadmin/blob/master/lib/active_admin/base_controller.rb#L38

Skipping authorization for certain methods

Per the Agile Development book, I have an Admin MVC that controls how users log in. In ApplicationController, I have a before_filter that checks for authorization. So, this will check that the user has logged in for every page.
The problem is that I want everyone to be able to access the new method, for example, in Users (that is, anyone should be able to create a new user -- naturally! Only admin users should have access to the other methods in UsersController such as edit, etc.). What's the best way to do that?
You can either of this
before_filter :except=>[:method_name] #methods you want to skip filter
OR
before_filter :only=>[:method_name] #methods you want to be filtered before called.
EDITED
before_filter :filter_method, :except=>[:method_name] #methods you want to skip filter
OR
before_filter :filter_method, :only=>[:method_name] #methods you want to be filtered before called.
You can use the skip_before_filter method in child controller classes to skip the default filter processing. For example:
class UsersController < ApplicationController
skip_before_filter :authorize, :only => [:new, :create]
end
—Will skip the before filter named :authorize only for the new and create actions within the users controller i.e. the filter will still get applied for all other actions.
I would also suggest using CanCan gem for authorization as it has a really simple and clean way to define authorization rules.
http://github.com/ryanb/cancan

Resources