Separate actors and create different roles
Allow different roles and permissions (e.g. normal users vs. admins) in your app by separating actors with namespacing and actor specific controllers.
Add an admin field in your users table which takes a boolean value.
# schema.rb create_table "users", force: true do |t| t.string "email" t.string "password_digest" t.string "full_name" t.datetime "created_at" t.datetime "updated_at" t.boolean "admin" end
Create a namespace in your routes
- This allows us to specify how the actor "admin" can interact and have access to the resource "posts". In this case see and delete "posts".
- For different actors we create different namespaces, i.e. adding another actor, such as a "superadmin" requires a new namespace.
- You now have new routes, such as
admin_posts_path
linking to the controller actionadmin/posts#index
. The corresponding URL will readdomain.com/admin/posts
.
# routes.rb namespace :admin do resources :posts, only: [:index, :destroy] end namespace :superadmin do resources :users, only: [:index, :create, :destroy] end
- This allows us to specify how the actor "admin" can interact and have access to the resource "posts". In this case see and delete "posts".
Create the actor specific admin controller
# controllers/admin/posts_controller.rb class Admin::PostsController < ApplicationController def index @posts = Post.all end def destroy end end
Nest your views under the same folder structure
- views/admin/posts/index.html.erb
Secure access by restricting admin urls to admin users
before_action :ensure_admin def ensure_admin flash[:error] = "You do not have permission to access this area." redirect_to root_path unless current_user.admin? end
Structure your controllers with inheritance to account for different roles
# controllers/posts_controller.rb
class PostsController < AuthenticatedController
# standard controller actions
# ...
end
# controllers/authenticated_controller.rb
class AuthenticatedController < ApplicationController
before_action :ensure_sign_in
# :ensure_sign_in is set as a helper method in the ApplicationController
end
# contollers/admins_controller.rb
class AdminsController < AuthenticatedController
before_action :ensure_admin
def ensure_admin
flash[:error] = "You do not have permission to access this area."
redirect_to root_path unless current_user.admin?
end
end
# controllers/admin/posts_controller.rb
class Admin::PostsController < AdminsController
def index
@posts = Post.all
end
end
A SuperAdminController would inherit from AdminsController, because a "SuperAdmin" also has to be "Admin".
Keep in mind that your login doesn't redirect to the normal views, but checks for admin status and redirects to the corresponding view.