🚫

GraphQL-Ruby で権限制御を行う方法

2023/04/08に公開

はじめに

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 で利用することができます。

graphql_controller.rb
  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