Railsアプリケーションのユーザー権限を管理する完全ガイド
この記事はもともとは書かれていたRenata Marques でHoneybadger Developer Blog .
Webアプリケーションの一般的な要件は、特定のロールと権限を割り当てる能力です.
多くの種類のウェブアプリケーションは、制限されたアクセスを提供する際に管理者と通常のユーザーを区別します.これは、ユーザーが管理者であるかどうかを判断する単純なBooleanを使用して行われます.しかし、ロールとパーミッションは、はるかに複雑になることができます.
アプリケーションの値は、特定のデータとアクションへのアクセスを制限します.それは間違いなく何かを台無しにしたくないです.このポストでは、基本的なRuby on Railsアプリケーションでロールとパーミッションを実装する方法について説明します.
いいえ、特にあなたのアプリケーションが小さいならば、あなたは宝石を必要としません、そして、あなたはコードベースにより多くの依存関係を加えるのを避けたいです.
しかし、選択肢を探している場合は、ロールとパーミッションを扱う最も人気のあるGemです. Devise
deviseは認証とロール管理のための宝石です、そして、それは本当に複雑で堅牢な解決です.
Githubで21.7 Kの星で、それはこのポストで最も人気のあるレポです、しかし、それは役割管理より多くをします.これは、認証ソリューションとして知られているので、非常に堅牢なライブラリが必要な場合は、コードベースに適用されます. Pundit :
PunditはシンプルなRubyオブジェクトを使用する宝石です、そして、おそらく、我々はカバーする最も簡単な方針宝石です.使用するのが簡単で、最小限の承認をして、純粋なルビーを使用することに似ています.Githubの上で7.3 Kの星で、それは現在最も人気のある政策宝石です. CanCan :
Cancanは、指定されたユーザーがアクセスできるようにするリソースを制限する認証ライブラリです.しかし、カンカンは何年も放棄されており、唯一のレール3と以前のリリースで動作します. CanCanCan :
CancancanはRubyおよびRuby on Rails用の別の認証ライブラリです.それはCancanに代わるもので、現在維持されています.Githubの上で4.9 Kの星で、それは最も人気があります、しかし、それはかなりよく働き、よく維持されます. これらのすべての宝石は素晴らしいですが、プレーンRubyで自分自身を許可するのは難しくありません.方針オブジェクトパターンと呼ばれる戦略を使用して、宝石なしで許可を管理する方法をあなたに教えます.
Policyオブジェクトは、パーミッションとロールを処理するためのデザインパターンです.あなたは何か誰かがアクションを実行するために許可されているかどうかを確認する必要があるたびにそれを使用することができます.それは複雑なビジネスルールをカプセル化し、簡単に別のルールを持つ他のポリシーオブジェクトに置き換えることができます.すべての外部依存関係は、ポリシーオブジェクトに注入され、許可チェックロジックをカプセル化します.
これは、きれいなコントローラとモデルに終わります.Pundit、Cancan、およびCancananのような宝石はこのパターンを実装することができます.
返り値はboolean値でなければなりません 論理は単純でなければならない メソッドの内部では、渡されたオブジェクトのメソッドのみを呼び出す必要があります
命名規則から始めましょうファイル名が
このメソッドでは、
以下にコード例を示します:
あなたのアプリケーションが制限されたアクセスと制限された行動の1つ以上のタイプを持つとき.例えば、以下のように投稿を作成できます. 少なくとも一つのタグ 管理者と編集者だけがそれらをつくることができる制限 エディタが検証される必要がある要件. 以下に例を示します.
まず始めましょう
アプリケーション内のポリシーディレクトリを作成する
コントローラの動作をテストするのは簡単です.
ポリシーパターンの概念は小さいが、大きな結果を生む.
単純または複雑なアクセス許可に対処するたびにポリシーオブジェクトを適用することを検討してください.rspecでテストするとき、データベースレコードを使う必要はありませんポリシー
純粋にRubyオブジェクトで、テストが簡単で高速になります.
Webアプリケーションの一般的な要件は、特定のロールと権限を割り当てる能力です.
多くの種類のウェブアプリケーションは、制限されたアクセスを提供する際に管理者と通常のユーザーを区別します.これは、ユーザーが管理者であるかどうかを判断する単純なBooleanを使用して行われます.しかし、ロールとパーミッションは、はるかに複雑になることができます.
アプリケーションの値は、特定のデータとアクションへのアクセスを制限します.それは間違いなく何かを台無しにしたくないです.このポストでは、基本的なRuby on Railsアプリケーションでロールとパーミッションを実装する方法について説明します.
許可を管理するために宝石が必要ですか?
いいえ、特にあなたのアプリケーションが小さいならば、あなたは宝石を必要としません、そして、あなたはコードベースにより多くの依存関係を加えるのを避けたいです.
しかし、選択肢を探している場合は、ロールとパーミッションを扱う最も人気のあるGemです.
deviseは認証とロール管理のための宝石です、そして、それは本当に複雑で堅牢な解決です.
Githubで21.7 Kの星で、それはこのポストで最も人気のあるレポです、しかし、それは役割管理より多くをします.これは、認証ソリューションとして知られているので、非常に堅牢なライブラリが必要な場合は、コードベースに適用されます.
PunditはシンプルなRubyオブジェクトを使用する宝石です、そして、おそらく、我々はカバーする最も簡単な方針宝石です.使用するのが簡単で、最小限の承認をして、純粋なルビーを使用することに似ています.Githubの上で7.3 Kの星で、それは現在最も人気のある政策宝石です.
Cancanは、指定されたユーザーがアクセスできるようにするリソースを制限する認証ライブラリです.しかし、カンカンは何年も放棄されており、唯一のレール3と以前のリリースで動作します.
CancancanはRubyおよびRuby on Rails用の別の認証ライブラリです.それはCancanに代わるもので、現在維持されています.Githubの上で4.9 Kの星で、それは最も人気があります、しかし、それはかなりよく働き、よく維持されます.
ポリシーオブジェクトパターン
Policyオブジェクトは、パーミッションとロールを処理するためのデザインパターンです.あなたは何か誰かがアクションを実行するために許可されているかどうかを確認する必要があるたびにそれを使用することができます.それは複雑なビジネスルールをカプセル化し、簡単に別のルールを持つ他のポリシーオブジェクトに置き換えることができます.すべての外部依存関係は、ポリシーオブジェクトに注入され、許可チェックロジックをカプセル化します.
これは、きれいなコントローラとモデルに終わります.Pundit、Cancan、およびCancananのような宝石はこのパターンを実装することができます.
純粋なポリシーオブジェクト規則
実装
命名規則から始めましょうファイル名が
_policy
最後に適用される接尾辞とクラスと方針.このメソッドでは、
?
文字(例えば、UsersPolicy#allowed?
).以下にコード例を示します:
class UsersPolicy
def initialize(user)
@user = user
end
def allowed?
admin? || editor?
end
def editor?
@user.where(editor: true)
end
def admin?
@user.where(admin: true)
end
end
どのシナリオで私はそれらを使用する必要がありますか?
あなたのアプリケーションが制限されたアクセスと制限された行動の1つ以上のタイプを持つとき.例えば、以下のように投稿を作成できます.
class PostsController < ApplicationController
def create
if @post.tag_ids.size > 0
&& (current_user.role == ‘admin’
|| (current_user.role == ‘editor’ && current_user.verified_email))
# create
end
end
end
上記の条件チェックは長く、醜い、読みにくいので、ポリシーオブジェクトパターンを適用する必要があります.まず始めましょう
PostsCreationPolicy
.class PostsCreationPolicy
attr_reader :user, :post
def initialize(user, post)
@user = user
@post = post
end
def self.create?(user, post)
new(user, post).create?
end
def create?
with_tags? && author_is_allowed?
end
private
def with_tags?
post.tag_ids.size > 0
end
def author_is_allowed?
is_admin? || editor_is_verified?
end
def is_admin?
user.role == ‘admin’
end
def editor_is_verified?
user.role == ‘editor` && user.verified_email
end
end
ポリシーオブジェクトを持つコントローラは以下のようになります.class PostsController < ApplicationController
def create
if PostsCreationPolicy.create?(current_user, @post)
# create
end
end
end
レールで方針オブジェクトを使う方法
アプリケーション内のポリシーディレクトリを作成する
/policies
すべてのポリシークラスを配置します.ときに、コントローラを呼び出す必要がある場合は、直接行動するか、またはbefore_action
:class PostsController < ApplicationController
before_action :authorized?, only: [:edit, :create, :update, :destroy]
def authorized?
unless ::PostsCreationPolicy.create?(current_user, @post)
render :file => "public/404.html", :status => :unauthorized
end
end
end
ポリシーオブジェクトをテストする方法
コントローラの動作をテストするのは簡単です.
require 'rails_helper'
RSpec.describe "/posts", type: :request do
describe "when user is not allowed" do
let(:user_not_allowed) { create(:user, admin: false, editor: false) }
let(:tag) { create(:tag) }
let(:valid_attributes) { attributes_for(:post, tag_id: tag.id) }
before do
sign_in user_not_allowed
end
describe "GET /index" do
it "return code 401" do
diet = Post.create! valid_attributes
get edit_post_url(post)
expect(response).to have_http_status(401)
end
end
end
end
ポリシーのテストも簡単です我々には、1つの責任だけの小さい方法がたくさんあります.require 'rails_helper'
RSpec.describe PostsCreationPolicy do
describe "when user is not allowed" do
let(:user) { create(:user, editor: false, admin: false) }
let(:user_editor) { create(:user, editor: true, email: verified) }
let(:tag) { create(:tag) }
let(:post) { create(:post, tag_id: tag.id) }
describe ".create?" do
context "when user is allowed" do
it "creates a new post" do
expect(described_class.create?(user_editor, post)).to eq(true)
end
end
context "when user is not allowed" do
it "does not create a new post" do
expected(described_class.create?(user, post)).to eq(false)
end
end
end
# ...more test cases
end
end
我々は、オブジェクトがすべてのシナリオで作成されるかどうかテストします.結論
ポリシーパターンの概念は小さいが、大きな結果を生む.
単純または複雑なアクセス許可に対処するたびにポリシーオブジェクトを適用することを検討してください.rspecでテストするとき、データベースレコードを使う必要はありませんポリシー
純粋にRubyオブジェクトで、テストが簡単で高速になります.
Reference
この問題について(Railsアプリケーションのユーザー権限を管理する完全ガイド), 我々は、より多くの情報をここで見つけました https://dev.to/honeybadger/complete-guide-to-managing-user-permissions-in-rails-apps-4dm6テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol