Reputation: 267020
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
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
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
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
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
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:
Upvotes: 9
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
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