user1464807
user1464807

Reputation: 63

Use action from a controller as filter in another controller in rails

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

Answers (2)

SteveTurczyn
SteveTurczyn

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

Graham S.
Graham S.

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

Related Questions