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
-
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.