RailsでToDoサービスを作ろう(第4回)〜Punditで認可の権限管理する〜
こんにちは、にゅ〜ぶるです。
こんにちは〜、ぶるこだよ〜💕
さて、第4回目ですね!前回は、こちら
今日は、「Punditで認可の権限管理する」について、進めていきたいと思います!
Punditとは、認可の仕組みを提供してくれるライブラリ(Gem)です。
https://github.com/varvet/pundit
認可、つまり、ユーザが機能を使えるかどうかを判定する処理を行います。
では早速、使ってみましょう。
まずは、Gemfileに以下を追加します。
gem 'pundit'
そして、Gemfileを修正したら「bundle install」ですね。
bundle install
これでPunditが使えるようになりました。
次は、設定ファイルを作っていきます。
まずは、generatorが用意されているので、それを使います。
rails g pundit:install
そうすると、app/policies/
配下にapplication_policy.rb
というファイルが作成されます。
class ApplicationPolicy attr_reader:user, :record def initialize(user, record) @user = user @record = record end def index? false end def show? false end def create? false end def new? create? end def update? false end def edit? update? end def destroy? false end class Scope attr_reader:user, :scope def initialize(user, scope) @user = user @scope = scope end def resolve scope.all end end end
initializer
で定義されるuser
はデフォルトでcurrent_user
が引数に割り当てられるようになっているので、deviseを使ってログイン機能を作った際はそのまま利用できます。record
の方には対応するモデルを割り当てていきます。※後述
では、この設定を有効にするために、有効にしたいControllerに次の1行を追加してください。各Controllerに追加しても良いですが、ApplicationControllerに追加する事で、継承されている全てのControllerで有効にする事ができますので、こちらを使いましょう。
class ApplicationController < ActionController::Base include Pundit end
次に、このファイルを継承して、各Controllerごとにファイルを作成していくことになります。
今回は、app/policies/
配下にtask_policy.rb
というファイルが作成しましょう。
class TaskPolicy < ApplicationPolicy end
・モデル名_policy.rb
でファイルを作成
・モデル名Policy
でクラスを作成
・def アクション名?
で認可ルールを作成
と言う感じです。
AppicationPolicyを継承しているため、独自にしたいアクション名のメソッドのみ作成すれば良いですが、AppicationPolicyのアクションに対応したメソッドを見て貰うと分かる通り、全てがfalseになっているため、全てが使えない状態になりますので、追加していきましょう。※後からでも良いです。
そして次は、各ControllerのアクションでPunditを使うように設定していきます。
各アクションに以下の1行を追加してください。
モデルのインスタンスを利用して判断する場合は、
authorize モデルのインスタンス
※このインスタンスがrecordに設定されます。
使わない場合は、
authorize モデル
と書き方が少し違います。
def update authorize @task ・・ 中略 ・・ end def index authorize Task ・・ 中略 ・・ end
では、設定したので、実際にブラウザでアクセスしてみましょう。
「rails s」で起動させたのち、「http://localhost:3000/tasks」にアクセスしてみてください。
エラーが出るよおおお😭
そうですね。
前述した通り、Deviseなどを使っている場合は、current_userが存在しますが、今回は省略させて貰っているので、作る必要がありますね。
固定で申し訳ありませんが、作っておきましょう…
class ApplicationController < ActionController::Base include Pundit def current_user # id=1のユーザを固定で返す User.find(1) end end
ではもう一度アクセスしてみてください。
まだエラー!!💢
落ち着いて、ちゃんとみてね笑
あ!
これが認可されなかったエラーなのか!
えへへ💕
そうなんだ。エラー画面を作る必要があるけど、まずは通常のエラー画面が出ればOKです。
では、各アクションの認可の仕組みを追加してみてください。
一覧画面や新規画面については、誰でもOKなので、常にtrueを返すようにしましょう。
参照や更新、削除については、そのTaskを作成したユーザが自分の場合のにOK(true)とする必要がありますね。
答えは、こんな感じ。
class TaskPolicy < ApplicationPolicy def index? true end def show? @record.user == @user end def create? true end def new? create? end def update? @record.user == @user end def edit? update? end def destroy? @record.user == @user end end
でも、これだけじゃダメですよ。
各アクションのメソッドで、Punditのauthorizeも必要ですね。
全てが完了したら、id=1のUserのTaskと、id=2のTaskを作るなどして、処理が正しく動いているか確認してみて下さい。
できたぁ💕
エラー画面については、rescue_fromを使ってごにょごにょしたり、固定のエラーページに飛ばしたり、強制でルートURLに遷移させたり、使い方は色々ありますので、自分にあった方法を見つけてみて下さい。
今回はここまでだよ。お疲れ様でした!
次回は、「一覧画面にRansack、kaminari」お楽しみにっ!!
最後まで読んでくれてありがとうございました!
現在、Railsのチュートリアル的な感じで、
「Todoサービスを作る!」をテーマにお送りしております。
アジェンダは、こちら
質問等ありましたら、コメントなりTwitterなりで頂ければ対応させて頂きますので、遠慮なく利用くださいね。
ディスカッション
コメント一覧
まだ、コメントがありません