Search code examples
ruby-on-railsrubyruby-on-rails-4devisesti

How do I make certain pages of my ruby on rails application inaccessible to one of my STI based Devise User model types?


I want one pages of my ruby on rails web application inaccessible to one of my STI model types. I have two models typeA and typeB inheriting from User. I have used the column type in the User table to implement STI. I am using Devise gem for User sessions. I want one webpage 'http://localhost:3000/rate' inaccessible to my typeA User. Whenever an User logs in who is of the type 'typeA', he does not have the option of seeing the link 'Rate'. But I also do not want him to be able to access that page by the link 'http://localhost:3000/rate'. If he tries to access it through that link, I want to sign him out and make him log in again. I managed this by using a piece of code in my Controller with the specific method for 'rate'.

def rate
  if current_user.type == "typeA"
    sign_out(current_user)
    redirect_to new_user_session_path
  else
    #Code for User of typeB
  end
end

This is working but I wanted to know if this can be done in a better way using before_filter :authenticate_user! or something else Right now my before_filter part looks like this

before_filter :authenticate_user!, except: [:index, :show]

Is there any way I can make a change to the upper code to achieve that functionality.
P.S: Maybe this can be done better if I had used roles or other gems like CanCan/Pundit but I do not have much time left to submit my project, so I do not want to get into all that right now.


Solution

  • you can add another before_filter on the controller you want to restrict the access just to confirm your STI user type without overiding devise's authenticate_user! filter.

    application_controller.rb

    class ApplicationController < ActionController::Base
    
      def confirm_user_type(user_type)
        redirect_to new_user_session_path unless current_user.is_a?(user_type)
      end
    
    end
    

    pages_controller.rb

    class PagesController < ApplicationController
      # must be authenticated to access
      before_filter :authenticate_user!
      # must be user of TypeA to access
      before_filter { |c| c.confirm_user_type(TypeA) }
    
      def rate
        ...
      end
    end
    

    Then, you can use the same filter before_filter { |c| c.confirm_user_type(TypeB) } for STI user type: 'TypeB'