Reputation: 63
I am trying to create an action that checks if a user is permitted to perform a certain action and if the user isn't then I want to redirect the user to an "Access Denied" view This is how my current setup is
class PermissionController < ApplicationController
def authorize(permission_id)
is_permitted = is_user_permitted(permission_id)
respond_to do |format|
format.js { render :json => {:is_permitted => is_permitted, :redirect => url_for(:controller => 'welcome', :action => 'index' , notice: "No access")}}
format.all { redirect_to :controller => 'welcome', :action => 'index' , notice: "No access" unless is_permitted == true }
end
end
end
I want to call the authorize action in the :before_filter of another controller.
How do I do that?
I can't put the authorize action in the ApplicationController since I want to define a route to this action in routes.rb
Upvotes: 1
Views: 1149
Reputation: 36880
@NickM has covered this in his comment... have OtherController
inherit from PermissionController
class PermissionController < ApplicationController
def authorize
...
end
end
class OtherController < PermissionController
before_filter :authorize
end
However I note your authorize method has a parameter?
You'll need to handle that in the before_filter clause. Assuming you can store permission_id
in a session variable...
class PermissionController < ApplicationController
def authorize(permission_id)
...
end
end
class OtherController < PermissionController
before_filter { |controller| controller.authorize(session[:permission_id] }
end
Upvotes: 0
Reputation: 1550
Why don't you try something like this, assuming you have the user's id stored in session:
class ApplicationController < ActionController::Base
def current_user
return unless session[:user_id]
@current_user ||= User.find(session[:user_id])
end
def authorize
# If user is NOT permitted
if !is_user_permitted(current_user)
# Response for you ajax here
respond_to do |format|
format.js { render :json => {:is_permitted => false, :redirect => url_for(:controller => 'welcome', :action => 'index' , notice: "No access")}}
format.all { redirect_to :controller => 'welcome', :action => 'index' , notice: "No access" }
end
end
end
end
class SomeOtherChildController < ApplicationController
before_filter :authorize, :only => [:show, :new, :edit]
# or you can use :except => [:index, :create, :destroy, :update] instead of :only.
# No authorization required
def index
end
# Authorization required
def show
end
# Authorization required
def new
end
# No authorization required
def create
end
# Authorization required (Ajax response for your "Edit" button)
def edit
# authorize method in ApplicationController will be called first
# If user is authorized, then the rest of this action will be executed
respond_to do |format|
format.js { render :json => {:is_permitted => true} }
end
end
# No authorization required
def update
end
# No authorization required
def destroy
end
end
Take this as an outline and general concept to what you might want to implement.
This is typically a concept I implement with permissions in my apps. You probably wouldn't want to put the Permissions logic in a separate child class controller, because in order to check permissions, you would either have to create a reference object of the PermissionsController (that is ugly and very un-Rails like) and use it within whatever controller you're trying to check permissions for, or you will have all other controller classes inherit from the PermissionsController, which isn't terrible, but certainly not ideal.
If users can have multiple types of permissions, you are probably better off creating a Permission model and controller, with a User has_many Permissions
relationship, where the logic in the authorize
method would become a bit easier to implement.
Upvotes: 0