Admin Gating in Ruby on Rails

The easiest way to protect your rails app
Say your rails app is looking awesome, but you need to protect the Create Update...(CRUD) functionality behind some authentication.  At the end of the tutorial, our app will have a realm that is view only, and another realm for editing and deleting stuff that begins with the /admin path.

There are 3 steps to this.
  1. Make the Admin Controllers
  2. Setup admin routes
  3. Admin in the Views

Make the Admin Controllers

Begin by making a controller app/controllers/admin_controller.rb.
This controller will use built in http_basic_authentication to require a password before anything occurs.
lang-ruby
      
          #app/controllers/admin_controller.rb.
class AdminController < ApplicationController
  http_basic_authenticate_with name: 'username',
   password: 'supersecret'
end
      
    
Now create the admin module folder in controllers/.  Copy all the existing controllers except admin_controller.rb into this new folder.  Your controllers directory should now look something like this
For all the copied controllers inside the controllers/admin folder, make them subclasses of AdminController instead of ApplicationController.  This will make sure we are authenticated before any of these controllers are called.
      
          
class Admin::CategoriesController < AdminController
  before_action :set_category, only: %i[ show edit update destroy ]
...
end
      
    
For the controllers outside of admin, remove the update, create, destroy and new methods so that your controllers have only index and show.  No way to edit or tamper with any content now with those controllers!
lang-ruby
      
          
class CategoriesController < ApplicationController
  before_action :set_category, only: :show

  # GET /categories or /categories.json
  def index
    @categories = Category.all
  end

  # GET /categories/1 or /categories/1.json
  def show
  end

  private
  ...
end
      
    

Setup Admin Routes

We'll use the route helper namespace for all the admin resources for CRUD.  Simply copy paste your resources into the namespace block.  Then with the resources outside the namespace block, make sure to specify they only have show and index actions for those controllers with  ", only: [:index, :show]"
      
          #application/config/routes.rb
Rails.application.routes.draw do
...
 namespace 'admin' do
  ...
  get 'categories' => 'categories#index', as: 'categories'
  post 'categories' => 'categories#create'
  post 'categories' => 'categories#create'

  resources :categories, except: [:index, :create], param: :slug, path: '/' do
    resources :makes, param: :slug
  end
 end # scope admin

  # visitor only resources
  resources :categories, only: [:index, :show], param: :slug, path: '/' do
    resources :makes, only: [:index, :show], param: :slug
  end
...
end
      
    

Admin in the Views

If you ran into a bunch of errors after changing the Routes.rb file that is to be expected.  So many views in the app use those CRUD routes, that are now somewhere else.  Let's fix this.

Start by copying your scaffold view folders into a new folder app/views/admin.  Now your directory should look something like this.

Next we have to go through all the non-admin views and remove all admin specific parameters.  Remove the edit pages, and all edit, new, and destroy buttons in non-admin views.

Then, in the admin views, add the :admin symbol before your @variables
[:admin, @make] # for show

# in a form helper
<%= form_with model: [:admin, category] do |form| %> 


This tells rails that /admin_ route is needed such that these paths connect correctly  to the admin controller not the regular show-only controllers.
Also add admin_ in front of all of your admin-only paths.  Below is an example for the edit.html.erb under views/admin/makes/
lang-erb
      
          
# for form helpers we have to specify the :admin param 
# so it knows what namespace to generate the path for
<h1>Editing make</h1>

<%= render "form", make: @make %>

<br>

<div>
  <%= link_to "Show this make", [:admin, @make] %> |
  <%= link_to "Back to makes", admin_makes_path %> |
  <%= link_to 'add instruments', admin_make_pick_path(@make) %>
</div>
      
    

Conclusion

In this tutorial we went over how to refactor your rails application to use a protected admin module.  We edited the views and controllers to make this all work as expected.

There was a lot of work behind this, so please have a look at the resources below for more on how to admin gate your ruby on rails app.

Sources:

github repository saxshop
The commit where you can see most of this work
Stack overflow:
  1. rails-routes-namespaces-and-form-for
  2. rails-using-link-to-with-namespaced-routes
Rails:
  1. Obie Fernandez rails-7-way
  2. https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic.html
  3. https://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

Previous Article: slugifying the saxshop app

updated: 2024-08-05 03:39:06 UTC
back to Web development more tutorials