Rails Can Can Canで権限管理 とてもgood!

CanCanCanという権限管理できるgemを利用してみる。

WEBの業務アプリで権限といえば、必要ないものはない!と言えるくらい大切なものです。

参考サイト 1000万以上のダウンロード すごい!

cancancan | RubyGems.org | your community gem host

本家サイト

GitHub - CanCanCommunity/cancancan: The authorization Gem for Ruby on Rails.

gemのインストール

gem 'cancancan', '~> 2.3'

1. Abilitiesのモデルをcancanを利用して作ります。

このクラスが大切になります。 モデルで管理するので安心です。

rails g cancan:ability

生成された、Abilityモデルで定義していきます。

alias_actionで、railsのコントローラーに記載するアクションを決定します。

alias_action :index,:create, :show, :update, :destroy, to: :crud でそれぞれのメソッドがクラッドできるということです。更新、削除等

class Ability
  include CanCan::Ability

  def initialize(user)
    
    # Define abilities for the passed in user here. For example:
    //ここでアクションを記載
    alias_action :index,:create, :show, :update, :destroy, to: :crud
    
      user ||= User.new # guest user (not logged in)
      
      if user.company_admin?
        
        can :crud, [User,Category], {company_id: user.company_id}
      else
        can [:update, :show], User, {company_id: user.company_id, id: user.id}
      end

ちなみに||= は左辺が未定義、または偽ならば、右辺を代入するという意味

Swiftの ?? に似ている。

userが未定義ならuserを作成しなさいの意味

   user ||= User.new 

user ||= User.new # guest user (not logged in)

もしログインしていなければ、カラユーザーを作成して判定用に用いる。

ログインしていなくて、アドレス叩く人もいるかも知れない。 saveしていないので、関係ないユーザーは作成されない。

if user.company_admin?

Userテーブルのcompany_admin カラムが真ならば

can :crud, [User,Category], {company_id: user.company_id}

そのユーザーは,User,CategoryテーブルのCRUDができます。 Userモデルのcompany_idカラムが  user.company_idと等しいものは。 という意味になります。

ここでcanメソッドの定義を見てみましょう

canは2つの引数を取ります。

第一引数は権限を設定しようとする、アクションです。

defでコントローラーに定義するやつですね。

第2引数は、それを設定しようとする、モデルになります。

can :update, Article

Articleモデルのupdateメソッドに権限設定するということですね。

引数に配列を渡すこともできます。

can [:update, :destroy], [Article, Comment]

そこにアクセス許可できるものを更に追加する場合は、条件のハッシュを渡せます。

それが上記の記載したコードになります。

{company_id: user.company_id}

これは、company_id が現在ログインしているuserのcompany_idが同じものという条件を追加しています。

つまり同じ会社のuserしか見れないということですね。 他の会社の情報が見れたら問題です。

あとは、load_and_authorize_resource メソッドを適用するコントローラーに記載します。

これで先程Abilityモデルで定義した内容がそのコントローラーに適用されます。

class UsersController < ApplicationController
  
  before_action :set_user, only: [:show, :edit, :update]
  before_action :sign_in_auth, only: [:show, :edit, :update]
//ここがcan can
  load_and_authorize_resource

上記のbefore_action :sign_in_auth, only: [:show, :edit, :update]メソッドでは、毎回コントローラーで表示する度に、関数をセットしていて 非常に危ない持ち方をしていた。

cancanでモデルで一括管理できるのは大変にありがたい。

この後、画面遷移でもadmin がfalseのuserは特定の画面に遷移できなかった。コントローラーごとにメソッドを書かなくてよいのは大変にありがたい。

ほかサイトではroleカラムなどを追加してenumなどで状態を管理していた。

このサイトは、管理したいuserモデルにcompany_adminカラムをあらかじめ持っていた箇所が違う。

参考されるときは、まず管理したいモデルに、Bool型のadminカラムを追加してからにして下さい。