アクションポリシーを使用したGraphSQL APIのパーミッションの公開
15950 ワード
今日は、私は私の人生の誕生日の記念日Rails Appsで- 1年の試行錯誤、ミスとヒット、WTF - Sとの完全な記念日です.
オープンソース中毒者として、私は特にGraphqlで働くのが好きでした:それはむしろ若い技術です、そして、したがって、貢献(少なくとも、Ruby Worldで)と実験の機会がたくさんあります.
そして今、私はそのような実験の結果を提示している
この記事を書いている間、私はRammsteinを聞いています🎸)
Graphqlの作業を始めたのと同じ時間に、新しいRuby認証ライブラリを発表しました.Action Policy , 世界へ.
アクションポリシーは、私はここ数年で取り組んできた複数のプロジェクトから抽出されています.それはイデオロギー的に似ているPundit (最初はそれの上に構築された)が、ボックスの追加機能の束を提供しています(そして非常に異なるアーキテクチャを内部に持っている).
これらの機能の一つは、認証チェックが失敗した理由について追加のコンテキストを提供する機能ですfailure reasons トラッキング
この機能は長い間、暗い馬でした、我々がほとんど我々がGraphqlで働き始めたまで、我々はほとんど(ほとんどデバッグ目的のために)使用しました-それは、醜いアヒルが美しい白鳥に変わった時です.
我々のコードで尋ねるたびに、「それをするのを許されるユーザーですか?」我々は認可の行為を行う.
GraphSQLを扱うとき、この質問はより具体的なものに分けることができます. ユーザーは、オブジェクト(特定のタイプの、または、グラフの特定のノードの)と対話するのを許されますか? ユーザーはこの突然変異を実行したり、このサブスクリプションを購読するか? 別の関連する側面は、データスコープである.フィルタコレクションは、すべての単一の項目をチェックする代わりに、ユーザのパーミッションに従っている.
The
だからこそ私は開発を始めました
問題は解決されているようでした:アクセス許可をチェックして、例外を上げるためにAPIで方針クラスで定義された認可とスコーピング規則を使用するのは楽になりました.後者は例外を上げるのですが、パーミッションの欠如についてユーザーに知らせる最善の方法ではありませんでした.
これらの例外を防ぎ、フロントエンドクライアントに対してどのような動作が許可されているかを説明します.
の問題pushing current user's permissions クライアント(フロントエンド/モバイルアプリケーション)への情報は、新しいされていませんそれは、Grapqlが生まれる前に、何年も存在しました.
問題は、クライアントがどのアクションをユーザーに許可されているかを確認する方法(および表示/非表示特定のボタン/リンク/コントロール)に翻訳することができます?
どのように解決するには?
たとえば、承認モデル(ロール、パーミッションセット)だけを通過し、承認規則クライアント側を実装(すなわち複製)するようにしてください.そのような重複は、足で自分を撃つ最も簡単な方法です.
そして、この単一のソースのソースは、通常、サーバーをチェックします.
したがって、我々のポリシー規則をクライアント互換形式に変換する必要があります.例えば、JSONオブジェクトです.
ユーザーのJSONオブジェクトへのすべての可能な認証ルールをダンプするのは良いアイデアではありません.うまくいけば、GraphSQLの利点の一つは、必要なデータだけを要求する能力です.
だから、我々は追加の簡単なアイデアを始めた
ほとんどの場合、行動が許されているか否かを知っていることがわかった
ユーザーがイベントにRSVPを許可するかどうかをチェックする規則の簡単な例を考えます.
RSVPが閉じられるとき、我々は「RSVPはこのイベントのために閉じられました」メッセージを見せたいです;これ以上の席が利用できない場合は
どのように、我々は我々の方針からこの情報を得ることができますか?使用failure reasons 機能性!
我々のルールを少し変更する必要があります.
よろしい.ここでアクションポリシーとi18n integration .
メッセージをlocaleファイルに追加しましょう.
には
クライアントの視点から、次のようになります.
認証情報を取得するための標準APIがあります 認証を行うための単一の抽象レイヤを持っています(ポリシークラス) スキーマへの認証ルールの追加は簡単です(そして、アクションポリシーのおかげで)ですtestability , テストも簡単です. そして、すべての機能を使用するときに無料で得る
記事を読むhttps://evilmartians.com/chronicles !
オープンソース中毒者として、私は特にGraphqlで働くのが好きでした:それはむしろ若い技術です、そして、したがって、貢献(少なくとも、Ruby Worldで)と実験の機会がたくさんあります.
そして今、私はそのような実験の結果を提示している
action_policy-graphql
gem , どちらが接着するかGraphQL Ruby and Action Policy 認証ライブラリ.待機、アクションポリシーは、IST DAS *だった?
この記事を書いている間、私はRammsteinを聞いています🎸)
Graphqlの作業を始めたのと同じ時間に、新しいRuby認証ライブラリを発表しました.Action Policy , 世界へ.
アクションポリシーは、私はここ数年で取り組んできた複数のプロジェクトから抽出されています.それはイデオロギー的に似ているPundit (最初はそれの上に構築された)が、ボックスの追加機能の束を提供しています(そして非常に異なるアーキテクチャを内部に持っている).
これらの機能の一つは、認証チェックが失敗した理由について追加のコンテキストを提供する機能ですfailure reasons トラッキング
この機能は長い間、暗い馬でした、我々がほとんど我々がGraphqlで働き始めたまで、我々はほとんど(ほとんどデバッグ目的のために)使用しました-それは、醜いアヒルが美しい白鳥に変わった時です.
To learn more about Action Policy and its features check out the slides from the most recent talk I gave at Seattle.rb early this year: https://speakerdeck.com/palkan/seattle-dot-rb-2019-a-denial.
認可とグラフ
Authorization is an act of giving someone official permission to do something (not to be confused with authentication).
我々のコードで尋ねるたびに、「それをするのを許されるユーザーですか?」我々は認可の行為を行う.
GraphSQLを扱うとき、この質問はより具体的なものに分けることができます.
The
graphql
宝石基礎authorization support を通じて#authorized?
フックとscoping support を通じて#scope_items
フック:それは最初に十分に良いことができますが、ボイラー板の量のためによくスケールしません.だからこそ私は開発を始めました
action_policy-graphql
gem –フィールド認証とスコープのためのより良いAPIを提供するにはGraphQL Pro for pundit
and cancancan
). このようにAPIを説明します.# field authorization example (`authorize: true`)
field :home, Home, null: false, authorize: true do
argument :id, ID, required: true
end
# data scoping using policies (`authorized_scope: true`)
field :events, EventType.connection_type, null: false, authorized_scope: true
この実装はfield extensions 内部的には、それは上に構築するよりも柔軟になった#authorized?
and #scope_items
フック.問題は解決されているようでした:アクセス許可をチェックして、例外を上げるためにAPIで方針クラスで定義された認可とスコーピング規則を使用するのは楽になりました.後者は例外を上げるのですが、パーミッションの欠如についてユーザーに知らせる最善の方法ではありませんでした.
これらの例外を防ぎ、フロントエンドクライアントに対してどのような動作が許可されているかを説明します.
クライアントにその権利について知らせる
の問題pushing current user's permissions クライアント(フロントエンド/モバイルアプリケーション)への情報は、新しいされていませんそれは、Grapqlが生まれる前に、何年も存在しました.
問題は、クライアントがどのアクションをユーザーに許可されているかを確認する方法(および表示/非表示特定のボタン/リンク/コントロール)に翻訳することができます?
どのように解決するには?
たとえば、承認モデル(ロール、パーミッションセット)だけを通過し、承認規則クライアント側を実装(すなわち複製)するようにしてください.そのような重複は、足で自分を撃つ最も簡単な方法です.
You should rely on a single source of authorization truth.
そして、この単一のソースのソースは、通常、サーバーをチェックします.
したがって、我々のポリシー規則をクライアント互換形式に変換する必要があります.例えば、JSONオブジェクトです.
ユーザーのJSONオブジェクトへのすべての可能な認証ルールをダンプするのは良いアイデアではありません.うまくいけば、GraphSQLの利点の一つは、必要なデータだけを要求する能力です.
だから、我々は追加の簡単なアイデアを始めた
canDoSmth
我々のGraphSQLタイプへのブールフィールドclass EventType < Types::BaseType
# include Action Policy helpers (`authorize!`, `allowed_to?`)
include ActionPolicy::Behaviour
field :can_destroy, Boolean, null: false
def can_destroy
# checks the EventPolicy#destroy? rule for the object
allowed_to?(:destroy?, object, context: {user: context[:current_user]})
end
end
クライアントは、イベントを削除することができるかどうかをサーバに問い合わせることができます.query {
event(id: $id) {
canDestroy # true | false
}
}
また、マクロを追加して認証フィールドを定義して、ボイラー板を減らすことができました.class EventType < Types::BaseType
include ActionPolicy::Behaviour
expose_authorization_rules :destroy?, :edit?, :rsvp?
end
「まだそこにいるのですか?」いいえ.クライアントがより多くのコンテキスト
ほとんどの場合、行動が許されているか否かを知っていることがわかった
true
or false
) 十分ではありません:また、ユーザーに通知を表示する必要があります(または“なぜ?”質問に答えてください).そして、いくつかの状況では、このメッセージを私たちがこの行動を禁止した理由によって異なります.ユーザーがイベントにRSVPを許可するかどうかをチェックする規則の簡単な例を考えます.
def rsvp?
allowed_to?(:show?) && # => User should have an access to this event
rsvp_open? && # => RSVP should be open
seats_available? # => There must be seats left
end
私たちは最後の2つのチェックに最も興味を持っています(ユーザーがイベントへのアクセスを持たないならば、それはRSVPへの許可を求めるべきではありません).RSVPが閉じられるとき、我々は「RSVPはこのイベントのために閉じられました」メッセージを見せたいです;これ以上の席が利用できない場合は
どのように、我々は我々の方針からこの情報を得ることができますか?使用failure reasons 機能性!
我々のルールを少し変更する必要があります.
def rsvp?
allowed_to?(:show?) &&
# wrapping method call into a `check?` method
# tracks the failure of this check (i.e. when it returns false)
check?(:rsvp_open?) &&
check?(:seats_available?)
end
次に、認証チェック結果から追加のコンテキストを取得できます.policy = EventPolicy.new(record: event, user: user)
# first, apply the rule
policy.apply(:rsvp?)
# now we can access the result object and its reasons
# for example, details hash contains the checks names grouped
# by a policy
policy.result.reasons.details #=> {event: [:rsvp_open?]} or {event: [:seats_available?]}
待つ?詳細ハッシュ?識別子?我々は人間に読めるメッセージが必要です!よろしい.ここでアクションポリシーとi18n integration .
メッセージをlocaleファイルに追加しましょう.
en:
action_policy:
policy:
event:
rsvp?: "You cannot RSVP to this event"
rsvp_opened?: "RSVP has been closed for this event"
seats_available?: "This event is sold out"
ローカライズされたメッセージにアクセスするには、#full_messages
結果オブジェクトについて:policy.result.reasons.full_messages #=> ["RSVP has been closed for this event"]
# to access the top-level (rule) message
policy.result.message #=> "You cannot RSVP to this event"
今すぐGraphSQLに戻ってexpose_authorization_rules
マクロを使用してフィールドを定義するAuthorizationResult
種類:には
reasons
フィールドオブアFailureReasons
種類:クライアントの視点から、次のようになります.
query {
event(id: $id) {
canDestroy {
value # true | false
message # top-level message
reasons {
details # JSON-encoded failure details
fullMessages # human-readable messages
}
}
}
}
このアプローチの長所は何ですか.action_policy-graphql
gem !記事を読むhttps://evilmartians.com/chronicles !
Reference
この問題について(アクションポリシーを使用したGraphSQL APIのパーミッションの公開), 我々は、より多くの情報をここで見つけました https://dev.to/evilmartians/exposing-permissions-in-graphql-apis-with-action-policy-1mfhテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol