activeadminの管理者権限付与の方法(ローカル環境)

こんにちは!kossyです!





今回はactiveadminでローカル環境に管理者権限を付与するやり方をブログに残したいと思います。
activeadminはRailsアプリケーションに簡単に管理者画面を実装できるgemです。




前提

Userモデル、及びusersテーブルに一つ以上レコードがあることを前提に話を進めます。


以下、導入手順です。


方法

Gemfileへの追加

Gemfile
gem 'activeadmin'

コマンドの実行

ターミナル(userモデルが作成済みの場合)
$ rails g active_admin:install --skip-users

ここでrails db:migrateするところですが、
このまま実行するとactive_admin_commentsというテーブルが作成されますので、
コメントテーブルが不必要ということであれば、マイグレーションファイルを削除してください。

管理者画面にコメントモデルを表示させないようにする処理

config/initializers/active_admin.rb

  # == Admin Comments
  #
  # This allows your users to comment on any resource registered with Active Admin.
  #
  # You can completely disable comments:
  # config.comments = false
  #
  # You can change the name under which comments are registered:
  # config.comments_registration_name = 'AdminComment'
  #
  # You can change the order for the comments and you can change the column
  # to be used for ordering:
  # config.comments_order = 'created_at ASC'
  #
  # You can disable the menu item for the comments index page:
  config.comments_menu = false <=ここのコメントアウトを外す
  #

サーバーを再起動し、ポート番号/adminにアクセスすると、


f:id:kossy-web-engineer:20180904220246p:plain
上記のような画面が表示されると思います(ヘッダーにアプリ名、モデル名が並びます)

次に、管理者画面から、ユーザー管理ができるようにカスタマイズします。
権限の管理を行うためにUserモデルにroleというカラムを追加します。


roleカラムの追加

$ rails g migration AddRoleToUser role:integer


マイグレーションファイルを編集

db/migration/2018XXXXXXXXXX_add_role_to_user.rb

class AddRoleToUser < ActiveRecord::Migration[5.1]
  def change
    add_column  :users,  :role,  :integer,  null:  false,  default:  0
  end
end
$  rails db:migrate

adminの場合、管理者権限が付与されますので、マイグレーションファイルでは
roleのデフォルト値を0(通常のuserの権限)としています。

app/models/user.rb

enum  role:  {  user:  0,  admin:  1  }

ステータス管理をしやすくするためにenum(列挙型)でデータを定義します。
これで0や1に意味を付与でき、可読性が向上します。
これでモデル側の準備は完了です。


次に、権限の制御のロジックを組みます。

authenticate_admin_user!メソッドの有効化

config/initializers/active_admin.rb

  # == User Authentication
  #
  # Active Admin will automatically call an authentication
  # method in a before filter of all controller actions to
  # ensure that there is a currently logged in admin user.
  #
  # This setting changes the method which Active Admin calls
  # within the application controller.
  config.authentication_method = :authenticate_admin_user! <=ここのコメントアウトを外す


application_controller.rbにauthenticate_admin_user!メソッドを定義
同時に例外処理も記述

app/controllers/application_controller.rb

  rescue_from SecurityError do |exception|
    redirect_to root_path, notice: '管理者画面へのアクセス権限がありません!'
  end

  protected

  def authenticate_admin_user!
    raise SecurityError unless current_user.try(:admin?)
  end

これで、管理者権限のないユーザーが管理者画面へのアクセスを試みた場合に、ルートパスへリダイレクトされるようになります。


次に、pryでユーザーのロールをadminに変更します。


consoleで権限の変更

$ rails c

[1] pry(main)> User.first.update_attributes(role: :admin)
[2] pry(main)> User.first.role            実行結果=> "admin"
[3] pry(main)> User.first.admin?      実行結果=> true

上記でロールにadminを指定したユーザでログインを行い、再度ポート番号/adminにアクセスして、
activeadminの管理者ページが表示されれば、ユーザの権限管理は完了です。


2018/09/29 追記

なぜか上記のやり方でrails cで管理者権限を追加できなくなっちゃいました、、、

[1] pry(main)> User.first.admin?
   (0.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  User Load (0.3ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> false
[2] pry(main)> User.first.role
  User Load (0.4ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> "user"
[3] pry(main)> User.first.update_attributes(role: :admin)
  User Load (0.4ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
   (0.2ms)  BEGIN
  User Exists (0.4ms)  SELECT  1 AS one FROM `users` WHERE `users`.`email` = BINARY '12345678@gmail.com' AND (`users`.`id` != 1) LIMIT 1
   (0.1ms)  ROLLBACK
=> false

カラムの更新方法について、
sakurawi.hateblo.jp
こちらの記事を参考に、

[5] pry(main)> User.first.update_columns(role: :admin)
  User Load (0.4ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
  SQL (12.7ms)  UPDATE `users` SET `users`.`role` = 1 WHERE `users`.`id` = 1
=> true
[6] pry(main)> User.first.admin?
  User Load (0.4ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> true
[7] pry(main)> User.first.role
  User Load (0.4ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> "admin"

できた!!!
もしupdate_attributesでロールの更新ができなければ、
update_columnsを試してみてください!


参考にさせていただいた記事
update_attributesとupdate_columnsの違い【Ruby on Rails】 - SakuraWi - BLog