AB10 AB10 - 4 months ago 11
Ruby Question

Setting up controller and its actions for Admin login only, not for a Users?

I have a model called

Article
.

In my
ArticlesController
, I have the article actions set up to where you have to be logged in as a User before you can do any actions except for my
index
and
show
actions.

Here's my
articles_controller.rb
:

class ArticlesController < ApplicationController

http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]

def index
@articles = Article.all
end

def show
@article = Article.find(params[:id])
end

def new
@article = Article.new
end

def edit
@article = Article.find(params[:id])
end

def create
@article = Article.new(article_params)

if @article.save
redirect_to @article
else
render 'new'
end
end

def update
@article = Article.find(params[:id])

if @article.update(article_params)
redirect_to @article
else
render 'edit'
end
end

def destroy
@article = Article.find(params[:id])
@article.destroy

redirect_to articles_path
end

private

def article_params
(params.require(:article).permit(:title, :text))
end
end


How can I set the
Article
actions so that only the admin can do basic CRUD functionality (create/read/update/delete) on
Article
?

Do I make an
Admin
model with
Devise
(I don't currently have an admin model)?

Is there a function or method that comes with
Devise
for admin usage in a controller?

Answer

Whether you're using a gem or rolling your own authorization, I would approach this by creating an additional controller. For regular users:

class ArticlesController < ApplicationController

  before_action :some_basic_authorization

  def index
    @articles = Article.all
  end

  def show
    @article = Article.find(params[:id])
  end

  ...
end

Your admin users will probably be doing more than performing CRUD actions for an article, so instead of repeating authorization in every controller, I'd suggest doing something like the following:

class AdminsController < ApplicationController
  some_admin_authorization
end

You'll then create dedicated admin controllers and inherit from this authorizing class. In your case, this might look like:

class AdminArticlesController < AdminsController

  def new
    @article = Article.new
  end

  def edit
    @article = Article.find(params[:id])
  end

  ...
end

Only admins will have access to actions specified in these controllers. As a side benefit, you can create custom show and index views that are specialized and more useful for admins. For example, they would include big edit and delete buttons that regular users don't need. This also keeps authorization logic and if/else statements out of your views.

In my opinion, using separate controllers and authorizing admins in one place makes code more readable and creates a nice separation of concerns. Read more about this here: http://guides.rubyonrails.org/action_controller_overview.html#http-basic-authentication

You can take this one step further by using an admin namespace, which you can read about here: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing