GraphQL-Ruby で権限制御を行う方法
はじめに
GraphQL-Ruby を利用している際に、特定の権限を持つユーザーにのみ、特定の mutation の実行を許可したいなんてことがあると思います。
今回は mutation の権限制御について調べたので共有します。
公式ドキュメントの GraphQL - Mutation authorization がベースとなっているので、こちらも合わせてご覧ください。
結論
ready?
メソッドを利用します
解説
ready? メソッドについて
ソースコード内のコメントには以下の記述があります。
Implement this hook to make checks before doing any work.
Google 翻訳で翻訳すると「このフックを実装して、作業を行う前にチェックを行います。」となります。
すなわち、 resolve
メソッドの前に ready?
メソッドが実行されるため、この中で権限制御を行うことができます。
参考: graphql-ruby/resolver.rb at v2.0.20 · rmosolgo/graphql-ruby
ready? メソッドを利用した実装例
実際に ready?
メソッドを利用した権限制御の実装を記載します。
ソースコードは GraphQL - Mutation authorization から引用します。
class Mutations::PromoteEmployee < Mutations::BaseMutation
def ready?(**args)
# Called with mutation args.
# Use keyword args such as employee_id: or **args to collect them
if !context[:current_user].admin?
raise GraphQL::ExecutionError, "Only admins can run this mutation"
else
# Return true to continue the mutation:
true
end
end
# ...
end
実装を確認すると、ready?
メソッド内で、保持している context
オブジェクトからユーザー情報を取得し、そのユーザーが Admin 権限を持っているかどうか確認していることがわかります。このように、 ready?
メソッドは resolver の実行前に実行され、事前チェックや前処理を行うためのメソッドとして利用されます。
if !context[:current_user].admin?
raise GraphQL::ExecutionError, "Only admins can run this mutation"
else
補足: context オブジェクトについて
補足として context オブジェクトにも触れます。GraphQL-Ruby において、context オブジェクトに格納した情報は resolver に共有することができます。
bundle exec rails generate graphql:install
等のコマンドで自動生成された graphql_controller.rb
には context オブジェクトが用意されており、ここにユーザー情報を格納し、各 resolver で利用することができます。
def execute
...
context = {
# Query context goes here, for example:
# current_user: current_user,
}
result = GraphqlTutorialSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
...
end
具体的なサンプルについてはここでは示しませんが、Server-side Authentication with GraphQL & Ruby Tutorial に記載されている内容が参考になるかもしれません。
以上です。
Discussion