🦓

[Rails]deviseでadmin認証を作る

に公開

はじめに

Deviseを使用してRailsアプリ内でユーザーモデルと認証を設定した場合、管理者(admin)用の独自のログインと管理画面を作成する手順をまとめてみました。

環境

Rails 7.0.4.3
ruby 3.2.1

前提

ユーザーテーブルにRoleカラムが作成されていることです。

bin/rails g migration AddRoleToUser role:integer
app/models/user.rb
class User < ApplicationRecord
  enum role: { general: 0, admin: 1 }
end

ルーティングを設定する

URLを/adminから始めたいので設定します。

config/routes.rb
Rails.application.routes.draw do
 devise_for :users, controllers: {
   registrations: 'users/registrations', # ユーザー用のコントローラー
  # 他のコントローラー設定
 }

  namespace :admin do
    devise_scope :user do
      get 'login', to: 'sessions#new'
      post 'login', to: 'sessions#create'
      delete 'logout', to: 'sessions#destroy'
    end
  end
end

devise_scope

devise_scope は、Deviseが提供するルーティングの設定に関するメソッドです。Deviseはユーザー認証と関連するルーティングを自動的に生成しますが、特定のアクションやコントローラーに対してカスタムの設定を適用したい場合に devise_scope を使用します。

通常、devise_scope は、Deviseのルーティングに追加の設定やオプションを適用するために使用されます。例えば、特定のコントローラーを指定したり、カスタムのアクションを追加したり、特定のURLパスを割り当てたりする場合に利用します。

devise_scope :user do
  get '/register', to: 'users/registrations#new'
  post '/register', to: 'users/registrations#create'
  
  get '/login', to: 'users/sessions#new'
  post '/login', to: 'users/sessions#create'
  delete '/logout', to: 'users/sessions#destroy'
end

上記の例では、devise_scope 内でカスタムのルートを定義しています。ここでは、ユーザーの新規登録(/register)、ログイン(/login)、ログアウト(/logout)に対してカスタムのURLパスを設定しています。

また、それぞれのルートは users/registrationsusers/sessions コントローラー内のアクションと対応しています。これにより、デフォルトの Devise のルーティングに追加のカスタムルートを設定して、アプリケーションの要件に合わせてユーザー登録とセッション管理をカスタマイズできるようになります。

このように devise_scope を使用することで、Deviseが提供するルーティングにカスタムの設定を組み込むことができます。カスタムルートの定義やルートの命名において、アプリケーションのニーズに合わせて調整することができます。

管理者用のコントローラーとビューを生成する

bin/rails generate devise:controllers admin
bin/rails generate devise:views admin

ロールカラムを許可する

deviseの許可するパラメーターにroleを追加します。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    # 管理者用のカラムを許可
    devise_parameter_sanitizer.permit(:sign_up, keys: [:role])
    devise_parameter_sanitizer.permit(:account_update, keys: [:role])
  end
end

Admin::Baseコントローラーを作成する

ロールごとにアクセス権限を制御するためにBaseコントローラーを作成します。

app/controllers/admin/base_controller.rb
class Admin::BaseController < ApplicationController
  before_action :authenticate_user!
  before_action :check_admin

  private

  def check_admin
    unless current_user&.admin?
      redirect_to root_path, alert: '権限がありません。'
    end
  end
end

レイアウトを宣言する

app/controllers/admin/base_controller.rb
class Admin::BaseController < ApplicationController
  layout 'admin'
end

管理者がログアウトしたら管理者用のログイン画面に遷移させたいのでafter_sign_out_pathヘルパーメソッドを使って定義します。

app/controllers/admin/sessions_controller.rb
class Admin::SessionsController < Devise::SessionsController
  layout 'admin'
  
  def after_sign_out_path_for(resource)
    admin_login_path
  end
end

レイアウトファイルを作成する

app/views/layouts/admin.html.erbを作成します。
管理画面用のテンプレートパーシャル
app/views/admin/layouts/_header.html.erbapp/views/admin/layouts/_footer.html.erbを作成し、adminレイアウトに追加します。

/admin/loginにアクセスするとadmin用のログイン画面を表示されていることを確認します。

20:26:36 web.1  | Started GET "/admin/login" for ::1 at 2023-08-13 20:26:36 +0900
20:26:36 web.1  | Processing by Admin::SessionsController#new as HTML
20:26:36 web.1  |   Rendering layout layouts/admin.html.erb
20:26:36 web.1  |   Rendering admin/sessions/new.html.erb within layouts/admin
20:26:36 web.1  |   Rendered admin/shared/_links.html.erb (Duration: 1.0ms | Allocations: 468)
20:26:36 web.1  |   Rendered admin/sessions/new.html.erb within layouts/admin (Duration: 4.2ms | Allocations: 2849)
20:26:36 web.1  |   Rendered admin/layouts/_header.html.erb (Duration: 0.7ms | Allocations: 383)
20:26:36 web.1  |   Rendered admin/layouts/_footer.html.erb (Duration: 0.3ms | Allocations: 101)
20:26:36 web.1  |   Rendered layout layouts/admin.html.erb (Duration: 14.7ms | Allocations: 12907)
20:26:36 web.1  | Completed 200 OK in 18ms (Views: 16.5ms | Allocations: 14107)

管理画面のルートパスを作成する

管理者がログインしたらアプリのルートパスではなく、管理画面のルートパスに遷移させます。

config/routes.rb
Rails.application.routes.draw do
  namespace :admin do
    resources :dashboard, only: [:index]
    root to: 'dashboard#index'
  end
end

adminのルートを確認します。

            Prefix Verb   URI Pattern                        Controller#Action
       admin_login GET    /admin/login(.:format)             admin/sessions#new
                   POST   /admin/login(.:format)             admin/sessions#create
      admin_logout DELETE /admin/logout(.:format)            admin/sessions#destroy
        admin_root GET    /admin(.:format)                   admin/dashboard#index

Dashboardコントローラーを作成する

Admin::Baseコントローラーを継承することにしましょう。

app/controllers/admin/dashboard_controller.rb
class Admin::DashboardController < Admin::BaseController
    def index

    end
end

ダッシュボードビューを作成する

app/views/admin/dashboard/index.html.erbにダッシュボードのビューを作成します。

終わりに

ユーザーモデルに管理者(admin)用の独自のログインと管理画面を作成することができました。

Discussion