zenet_logo

-株式会社ゼネット技術ブログ-

【rails】Active Adminで「閲覧限定ユーザ」機能を手軽に実装する方法

お疲れさまです、システム事業部の坂本です。
今回はタイトルの通り、Active Adminで「閲覧限定ユーザ」機能を手軽に実装する方法をお伝えします。

[ 今回の背景等 ]

とあるrails製のシステムにて、管理画面の実装に「Active Admin」というgemを使っていました。
github.com

このgemを利用することで、マスターデータの管理・追加・削除などが容易に実装できます。
ただ、デフォルトでは管理画面にログイン可能なユーザ全員が自由にデータの修正等が可能だったので、
「閲覧限定ユーザを設定出来るようにしたい」という要望が挙がりました。

しかし、コントローラー毎にわざわざ記載するのは画面数が多く工数が膨らみ、
今後のメンテナンスも大変になるので、「なるべくシンプルな方法で閲覧限定ユーザを実装出来ないか?」と検討していました。
調べて動作確認を行ったところ、以下のような方法で実現することが出来ました。

[ 実装方針 ]

Active Adminの設定ファイルをカスタマイズして、権限管理を行う

以下、実装方法となります。


[ 実装方法 ]

まずはじめに、Active Adminへのログインを行うためのモデルが「AdminUser」だと仮定します。

migrateファイルを利用し、新しいカラムを追加します。

■db/migrate/20220131103000_add_user_class_to_admin_users.rb

class AddUserClassToAdminUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :admin_users, :user_class, :integer, comment: 'ユーザ種別'
  end
end

その後migrateを行った上で、AdminUserのモデルに対してenumを使って
以下のようにenumを定義しておきます。

■app/models/admin_user.rb

class AdminUser < ApplicationRecord### 今回必要な設定以外は割愛 ###

  enum user_class: { admin: 1, viewer: 2 }
end

最後に、config/initializers/active_admin.rb(以下、activeadmin設定ファイル)に
before_actionを指定します。

■config/initializers/active_admin.rb

ActiveAdmin.setup do |config|
  ### 今回必要な設定以外は割愛 ###

  # This setting changes the method which Active Admin calls
  # (within the application controller) to return the currently logged in user.
  config.current_user_method = :current_admin

  config.before_action :check_user_permissions, except: [:index, :show]
  def check_user_permissions
    redirect_to admin_root_path, flash: { error: '権限がありません。' } if controller_name != 'sessions' && current_admin&.viewer?
  end
end

こうすることで、閲覧限定ユーザは「一覧画面の表示」「詳細画面の表示」以外が出来なくなります。

[ 細かい解説 ]

今回は、activeadmin設定ファイルの内容が鍵です。

まず、現在ログインしているユーザを取得するためのメソッドを「current_admin」とします。

config.current_user_method = :current_admin

続いてアクションを制限するために、before_actionをactiveadmin設定ファイルに定義します。
activeadmin設定ファイルにbefore_actionを設定すると、
activeadminで行われる全てのアクションに対してbefore_actionを設定することが出来ます。

今回は閲覧限定ユーザは「一覧画面の表示」と「詳細画面の表示」が行えればいいという前提なので、
index・show以外で権限を確認するメソッドが実行されるような設定を記載します。

  config.before_action :check_user_permissions, except: [:index, :show]

※カスタマイズされたメソッドがある場合、必要に応じて「except」にアクションを追加してください。

最後に、権限を確認するメソッドcheck_user_permissionsを書きます。

  • ログインに関する処理を行うコントローラ「SessionsController」では、権限を確認する必要が無いので飛ばします。
     → このコントローラを対象にすると、ログイン(create)・ログアウト(destroy)ができなくなってしまうため
  • それ以外のコントローラでは、ログインしているユーザが閲覧限定ユーザだった場合にのみ管理画面のトップ画面にリダイレクトさせるようにします。

上記の仕様をもとにすると、activeadmin設定ファイルに以下のようなメソッドを書く必要があります。

  def check_user_permissions
    redirect_to admin_root_path, flash: { error: '権限がありません。' } if controller_name != 'sessions' && current_admin&.viewer?
  end

以上3点をactiveadmin設定ファイルに記載することにより、Active Adminにて閲覧限定ユーザが
任意の編集画面に遷移しようとしたり、データの削除を実行しようと試みた場合は、
メソッドcheck_user_permissionsにより操作が自動でキャンセルされて
管理画面のトップ画面にリダイレクトされるようになります。


Active Adminの閲覧権限機能の実現で悩んでいる方のヒントになれば幸いです。
ありがとうございました。