Blankman
Blankman

Reputation: 267020

In Rails, how to have an /admin section, and then controllers within the admin section?

I want to have a /admin section in my application, and have routes within this /admin section like:

www.example.com/admin/ (only certain users have acess to this section)

then have controllers in this section like:

/admin/users/{add, new, etc}

What are my options for something like this? (using rails 3)

Upvotes: 20

Views: 15750

Answers (7)

DavidLyonsGarcia
DavidLyonsGarcia

Reputation: 458

When you're organizing controllers in subfolders you have to add the module line on top of the controller to match the "namespace". For example in my case I want the admin user to manage the manufacturers and that is in the next folder: /app/controllers/users/admin

Then I've a controller the heritages from the base controller like this:

module Users::Admin
  class Users::Admin::AdminController < ApplicationController
    before_action :authenticate_admin!
    private
    def authenticate_admin!
      unless current_user&.is_admin?
        redirect_to root_path, alert: 'You are not authorized to access this page'
      end
    end
  end
end

The the manufacturer_controller that is also in the /app/controllers/users/admin folder starts in this way:

module Users::Admin
  class Users::Admin::ManufacturersController < AdminController
    before_action :set_manufacturer, only: %i[show edit update]
    include Pagy::Backend

    @is_new = true
    @some_text = 'Hello World'

    def index
      # @manufacturers = current_user.manufacturers
      @q = current_user.manufacturers.ransack(params[:q])
      @q.sorts = 'name asc' if @q.sorts.empty?
      @pagy, @manufacturers = pagy(@q.result(distinct: true), items: 25)
    end
....

Upvotes: 0

stevenhaddox
stevenhaddox

Reputation: 1215

I prefer to do something similar to Todd's answer but slightly different. Rather than adding the before_filter to each controller related to Admin stuff I prefer to create an AdminController that all controllers related to admin actions can inherit from:

# config/routes.rb
namespace :admin do
  resources :users
end

# app/controllers/admin_controller.rb
class AdminController < ApplicationController
  before_filter :authorized?
  private
  def authorized?
    unless current_user.has_role? :admin
      flash[:error] = "You are not authorized to view that page."
      redirect_to root_path
    end
  end
end

# app/controllers/admin/users_controller.rb
class Admin::UsersController < AdminController
   ...
end

Upvotes: 44

justsee
justsee

Reputation: 933

Obviously what Todd said is correct. However if you're a fan of additional security through obscurity, you can also keep your new_admin_user url helpers and Admin:: namespaced controllers, but provide a less widely-used public url path with the following:

scope  :module => "admin", :as => 'admin', :path => 'xyz' do
 resources :user
end

A rake route with that setup will show routes along these lines:

new_admin_user GET  /xyz/users/new(.:format)  {:controller=>"admin/users", :action=>"new"}

I suppose the only actor this would thwart is an unsophisticated attacker who's crawled and compiled a bunch of Rails sites that provide system access at admin/, but I don't see any harm in daring to be different with your admin console paths really.

Upvotes: 3

K&#39;ao
K&#39;ao

Reputation: 330

Then in each admin controller you'll need a before_filter:

before_filter :authorized?
def authorized?
  #check if authorized here.
end

I think it's better if he puts this code into a main AdminController which inherits from ApplicationController, then each admin controller will inherits from this AdminController.

About Rails3, here is a good article about routes

Upvotes: 6

Jaime Bellmyer
Jaime Bellmyer

Reputation: 23307

As Todd mentioned, you want to add a namespaced route:

namespace :admin do
  resources :users
end

You also need to put your controllers, views, etc in subfolders of each of these sections called "admin/". If you're generating this from scratch, it's easy:

rails g controller admin/users

This may seem pretty complicated, but I have an article that walks through all of this, with a sample rails 3 app you can download to play around with it:

Routing in Ruby on Rails 3

Upvotes: 9

Todd
Todd

Reputation: 3508

Do something like this in your routes.rb:

  namespace :admin do
    resources :users
  end

See http://guides.rubyonrails.org/routing.html for more detail.

Then in each admin controller you'll need a before_filter:

before_filter :authorized?
def authorized?
    #check if authorized here.
end

Upvotes: 18

Sam 山
Sam 山

Reputation: 42863

application_controller.rb   
before_filter :if_namespace_is_admin?

def if_name_space_is_admin?
    #now you should check to see if the namespace is from admin
    #now you need namespaces because ruby ns confuse the f'out of me
end 

Upvotes: 2

Related Questions