Ronats
Ronats

Reputation: 329

How to set routes for specific users in rails 7

I am having an issue with Rails_admin. rails_admin is successfully added to the app and working fine.

Issue is when I am trying to set the routes to a specific role user.

My app consists of several role like user, client, admin etc. What I want here is only user with role 'admin' can access to rails_admin section by either using "link_to 'rails_admin_path'" or http://127.0.0.1:3000/admin.

Already I am having an admin section so I don't want to add any other login section for rails_admin, just need the features of rails_admin in my admin.

And I've a method called "check_admin" which will check the role of the current_user is admin or not

current_user.check_admin

#routes.rb

Rails.application.routes.draw do
   mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
end

Here what my requirement is, the given route can be only accessed by admin user

hints: check_admin or current_user.roles.admin.present?

Upvotes: 1

Views: 1378

Answers (4)

Chrismisballs
Chrismisballs

Reputation: 320

I'm pretty sure this is what constraints is for

https://guides.rubyonrails.org/routing.html#advanced-constraints.

https://www.mikewilson.dev/posts/rails-vanity-urls-with-route-constraints/

We can use a Route Constraint on our users route, so that if the :id from the route doesn’t match a username in our system, we return false and Rails moves on to the next route.

Explain about Route Constraint Rails

basically something like this in

lib/role.rb

class Roles   
    def initialize(&block)
       @block = block || lambda { |user| true }  
    end
        
     def matches?(request)
      user = current_user(request)
      user.present? && @block.call(user)  
     end
        
    def current_user(request)
#my users cookies are stored in A model called ActiveSessions
#what ever your Session cookies is goes here
      active = ActiveSession.find_by(id: 
       request.session[:current_active_session_id])
#then find user from that cookie
     User.find_by_id(active.user.id)   
    end 
end

then in routes:

constraints Roles.new { |user| user.roles == "ROLE" } do
#what ever routes you want access to based on constraint
end

Edit:

Would also add now that I had to deal with this that if you plan to access a **cookie**, not session, for querying you will have to do:

request.cookie_jar.encrypted[:whatever_name_here]

Note ROLE is what role you want to give access to based on the column attribute; i.e. admin, member, client, etc.

Upvotes: 3

Les Nightingill
Les Nightingill

Reputation: 6156

Upon request, expanding on my previous comment...

class AdminController < ApplicationController
  before_action :reject_non_admins

  def index
  end

  def show
  end

# etc... all the admin CRUD actions

private
  def reject_non_admins
    unless current_user.check_admin
      render "unauthorized.html" and return
    end
  end

end

so non-admin users are not prevented from accessing the sensitive admin pages, but they're just shown a page that tells them they're not allowed to see the content.

# app/views/admin/unauthorized.html

<p>Sorry, only admins can see this page</p>

Upvotes: 1

Ronats
Ronats

Reputation: 329

Solution

routes.rb

authenticate :user, -> (u) { u.roles.admin.present? } do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
end

Change route under a condition where it check for the particular role, in my case its "admin".

So the other users who are not an admin can't get an access to rails_admin in anyway

Upvotes: 2

Les Nightingill
Les Nightingill

Reputation: 6156

The routes configuration is not the correct place to prevent the non-admin user from accessing the page. The routes configuration has no concept of current_user.

It should be done in the controller.

def show
  unless current_user.roles.admin.present?
    render "unauthorized"
  end
  # default "show.html will render
end
   

Upvotes: 0

Related Questions