I am using existing rails application, where we currently use devise for authentication and Pundit for authorization. My requirement is to skip all policies scope authorization for all action in this existing rails application. How Can I do this?
I have tried below code but not worked:-
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery with: :exception
before_action :authenticate_user!, :set_default_timezone#, :modify_search_params
before_action :set_current_user
skip_after_action :verify_policy_scoped
#.....
end
Thanks in advance :)
Pundit provides skip_authorization to skip his authorization. Executing it before all actions of the controller will make it work for your requirement.
class ApplicationController < ActionController::Base
# ...
before_action :skip_all_authorization
private
def skip_all_authorization
skip_authorization
end
# ...
end
You need to skip both action authorization with an object (which are called by using authorize(object) and with a policy scope (called with policy_scope).
You can skip the hooks on your base class:
skip_after_action :verify_policy_scoped
skip_after_action :verify_authorized
Or just add another hook to skip them on your controller (my preferred approach)
after_action :skip_all_authorization
private
def skip_all_authorization
skip_policy_scope
skip_authorization
end
But by the way, you shouldn't need this unless you're ensuring the policy is called by adding the appropriate hooks.
Related
What might be causing this error in verify_authorized method and how to fix it?
Pundit adds a method to your controller called verify_authorized that ensures that the authorize method is called somewhere in your controller action. You likely setup an after_action that calls verify_authorized (https://github.com/elabs/pundit#ensuring-policies-and-scopes-are-used). Make sure you're calling authorize in each possible execution path through your controller action.
Alternatively, if you do not want to authorize that particular action, you can skip it:
class PagesControler < ApplicationController
include Pundit
after_action :verify_authorized, except: [:home]
...
end
or if you setup the after_action in an inherited controller:
class ApplicationController < ActionController::Base
include Pundit
after_action :verify_authorized
...
end
class PagesControler < ApplicationController
skip_after_action :verify_authorized, only: [:home]
...
end
I've built a Shopify app on Rails using shopify_app gem. I want to call a method immediately after a store owner installs the app, but I'm having trouble figuring out where I would call that.
What is the controller#action when a new instance of the app is created?
I have
class ApplicationController < ActionController::Base
include ShopifyApp::Controller
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
class AuthenticatedController < ApplicationController
before_action :login_again_if_different_shop
around_filter :shopify_session
layout ShopifyApp.configuration.embedded_app? ? 'embedded_app' : 'application'
end
class HomeController < AuthenticatedController
def index
#customers = ShopifyAPI::Customer.find(:all, :params => {:limit => 100})
end
end
class SessionsController < ApplicationController
include ShopifyApp::SessionsController
end
I am learning to use Pundit for authorization. But the way I see it is authorization for resources not pages. I want a user to be redirected to a unauthorized page if he/she is not authorized to visit the page using pundit.
For e.g.
class OnlyAdminCanVisitController < ApplicationController
before_filter :admin_authenticate
Stops a non-admin role user.
Also, I want to take care of made up scenarios like following(Considering there are 4 roles as Admin,Manager,Employee,Outsider. The design below is obiviously bad)
class AdminManagerCanVisitController < ApplicationController
before_filter :admin_or_manager_authenticate
class AdminEmployeeCanVisitController < ApplicationController
before_filter :admin_or_employee_authenticate
class AdminOutsiderCanVisitController < ApplicationController
before_filter :admin_or_outsider_authenticate
class AdminManagerEmployeeCanVisitController < ApplicationController
before_filter :admin_or_manager_employee_authenticate
I have 4 roles and would like to write pundit policies for these controllers which allows any combination of authorizations.
Let me know if pundit is designed to tackle this issue.
Thanks
There is not much difference between pages and resources actually. So you can solve your problem by rescuing a denied Authorization from your application_controller.rb :
class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
protected
def admin_authenticate
authorize current_user, :admin?
end
private
def user_not_authorized(exception)
# Redirect to whatever page you want if not authorized
end
end
You then need to define your policy. I generally create an admin? method in application_policy.rb (https://github.com/elabs/pundit#policies) so it is spread on my other policies as well :
class ApplicationPolicy
def admin?
# Logic to ensure the user is an admin
end
end
class UserPolicy < ApplicationPolicy
end
Then in your other controllers, just do as you did :
class OnlyAdminCanVisitController < ApplicationController
before_action :admin_authenticate
end
I am using rails 4, devise for authentication and Pundit for authorization. I have restricted my application to check for authorization on every controller by below code.
class ApplicationController < ActionController::Base
include Pundit
after_action :verify_authorized
#.....
end
However, i want to skip authorization for two specific controllers in my application (they are open to public, users do not need to sign in). How can i achieve it without removing verify_authorized in ApplicationController ?
skip_after_action :verify_authorized
I'm working with Rails 5 and I wanted to skip authorization in just one action but not the whole controller. So, what you can do according to the documentation is to use skip_authorization feature in the controller action as shown below:
class Admin::DashboardController < Admin::BaseController
def index
#organizers = Organizer.count
#sponsors = Sponsor.count
#brochures = Brochure.count
skip_authorization
end
def sponsors_approve
# some statements...
end
def organizers_approve
# some statements...
end
end
In this controller the only one action to be skipped is index, the other ones must be authorized.
I hope it could be useful for somebody else.
I am using devise and in my profile_controller.rb I have the usual 7 methods and an additional methods, now I am using before_filter as only authenticated user can access those methods but for just 1 method, I need it to bypass it. How to do it ?
before_filter :authenticate_user!
def index
...
end
...
def destroy
...
end
def edit_name
...
end
before_filter :authenticate_user!, except: :method_you_want_to_bypass
In this way you skip the call to authenticate_user! method when the current action is :method_you_want_to_bypass. This solution works in general, not only with Devise.