Suvajit Chakrabarty
Suvajit Chakrabarty

Reputation: 43

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.

Upvotes: 1

Views: 209

Answers (2)

mahemoff
mahemoff

Reputation: 46409

Try this:

class ApplicationController

  before_action :authenticate_user!

  def authorize_user!
    if current_user.type == "typeA"
      sign_out(current_user)
      redirect_to new_user_session_path
    end
  end

end

with your controller:

class SomeController < ApplicationController

    before_action :authorize_user!, except: [:index, :show]

    def top_secret
        ...
    end

end

I believe if a before_action (the new name for before_filter) renders or redirects, the action won't be processed.

Upvotes: 0

sa77
sa77

Reputation: 3603

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'

Upvotes: 1

Related Questions