こんにちは!kossyです!
さて、今回はgraphql-rubyで認可制御を行うready?メソッドとauthorized?メソッドについて、
備忘録としてブログに残してみたいと思います。
graphql-rubyでの認可制御
graphql-rubyのドキュメントを見ると、Mutationの認可制御メソッドとして、ready?メソッドとauthorized?メソッドが使えると記載があります。
それぞれどのような違いがあるのでしょうか。ソースコードを見てみましょう。
ready?メソッドのソースコードを見る
まずはソースコードを読んでみます。
def ready?(**args) true end
有無を言わさず true を返すメソッドになっていました。ちょっと意図がよくわからないので、コメントアウト部分を読んでみましょう。
Called before arguments are prepared.
Implement this hook to make checks before doing any work.argumentsが準備される前に呼び出されます。
このフックを実装して、resolverが実行される前にチェックを行います。If it returns a lazy object (like a promise), it will be synced by GraphQL
(but the resulting value won't be used).遅延実行されるオブジェクト(Promiseのようなオブジェクトです)を返す場合、GraphQLによって同期されます。
(ただし、結果の値は使用されません)。出典: graphql-ruby/lib/graphql/schema/resolver.rb at master · rmosolgo/graphql-ruby · GitHub
呼び出しのタイミングは、引数が準備される前とのことでした。
authorized?
こちらもソースコードを見てみます。
def authorized?(**inputs) self.class.arguments(context).each_value do |argument| arg_keyword = argument.keyword if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value) arg_auth, err = argument.authorized?(self, arg_value, context) if !arg_auth return arg_auth, err else true end else true end end end
コメントアウト部分を見てみます。
Called after arguments are loaded, but before resolving.
引数がロードされた後、resolverの前に呼び出されます。
出典: graphql-ruby/lib/graphql/schema/resolver.rb at master · rmosolgo/graphql-ruby · GitHub
とのことでした。よしなにオーバーライドしてもOKなようです。
ready?とauthorized?のユースケース
ready?は引数がロードされる前に実行されるとのことなので、引数の値抜きで権限チェックを行いたい時に使うのがいいと思います。
def ready? if context[:current_user].admin? true else raise GraphQL::ExecutionError, "Only admins can run this mutation" end end
逆にauthorized?メソッドは引数がロードされた後に実行されるとのことなので、引数の値込みで権限チェックを行いたい時に使うのがいいと思います。
例えば、管理者権限でも更新できない値があった場合に例外を発生させたりするパターンが考えられます。(履歴データとか)
def authorized?(**inputs) if context[:current_user].admin? && context[:current_user].can_edit_all?(inputs) true else raise GraphQL::ExecutionError, "Inculde Cannnot Edit Value" end end
勉強になりました。