0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Devise使用時にログイン中のモデルと異なるモデルを編集する方法(CompanyでログインしてStaffの編集・更新)

Posted at

概要

この記事では、RailsアプリケーションでDeviseとCanCanCanを使用して、CompanyStaff という二つのユーザーモデルを効果的に管理する方法を紹介します。
特に、Company モデルでログインしている状態で Staff モデルのデータを編集できるようにする際に生じた以下のエラーの解消法を詳しく解説します。

Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms | Allocations: 209)

※ブラウザでリンクを選択後、アクションに遷移する前に上記のエラーが生じたため、deviseの認証関連が原因ではないかとあたりをつけました。

1. 導入

本記事では、企業とその従業員をそれぞれ CompanyStaff モデルで管理するシナリオを想定しています。各モデルはDeviseによって認証が行われ、CanCanCanでアクセス権限が管理されます。この設定を通じて、モデルごとの認証と権限のカスタマイズ方法を学びます。

2. 環境設定

このチュートリアルを始める前に、以下のGemがインストールされていることを確認してください。

gem 'rails', '~> 6.0.0'
gem 'devise'
gem 'cancancan', '~> 3.0'

これらのGemをインストールした後、DeviseとCanCanCanの初期設定を行います。

rails generate devise:install
rails generate cancan:ability

3. Deviseのセットアップ

CompanyStaff モデルにDeviseを適用します。まずはモデルを生成し、Deviseのモジュールを追加します。

rails generate devise Company
rails generate devise Staff

次に、config/routes.rb でDeviseのルーティングを設定します。

devise_for :companies
devise_for :staffs

4. CanCanCanの権限設定

Ability クラスで、CompanyStaff のデータを編集できるように権限を設定します。

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new

    if user.is_a?(Company)
      can :manage, Staff, company_id: user.id
    end

    # その他の権限設定...
  end
end

5. エラー発生

上記の概要で述べたエラーがここで生じました。

Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms | Allocations: 209)

処理開始後にbinding.pryで処理を停止させることができなかったことと、Rails.logger.debugでログ取得をしようとしても何も情報を得られなかったため

  • controllerのcontrollerのアクション以前の処理
  • CanCanCan関連
  • Devise関連

のエラーを疑いました。

6. 対策

Staffs::RegistrationsController をカスタマイズして解決しました。

app/controllers/staffs/registrations_controller.rb
class Staffs::RegistrationsController < Devise::RegistrationsController
  before_action :set_staff, only: %i(edit update destroy)
  
  # ↓以下のauthenticate_staff!を追記(protected以下でオーバーライドしたものを使用する)
  before_action :authenticate_staff!, only: %i(edit update destroy) 
  load_and_authorize_resource :class => 'Staff', except: %i(create)
  before_action :configure_permitted_parameters, if: :devise_controller?

  def edit
    @staff = Staff.find(params[:id])
  end

  protected

  # 以下でauthenticate_staff!をオーバーライド
  def authenticate_staff!(opts = {})
    @staff = Staff.find(params[:id])
    unless staff_signed_in? || (company_signed_in? && @staff.company_id == current_company.id)
      redirect_to new_company_session_path, alert: 'アクセス権限がありません。'
    end
  end

  def set_staff
    if resource.present?
      @staff = Staff.find(resource.id)
    end
  end
  # その他の設定...
end

7. まとめ

DeviseとCanCanCanを用いて複数のモデルに対する認証と権限管理を行う方法を学びました。この技術は、大規模なRailsアプリケーションでのアクセス制御に非常に有効です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?