66 describe GraphQL ::Tracing ::PerfettoTrace do
77 include PerfettoSnapshot
88
9+ def trace_includes? ( json_str , test_str )
10+ json_str . include? ( Base64 . encode64 ( test_str ) . strip ) ||
11+ json_str . include? ( test_str )
12+ end
13+
914 class PerfettoSchema < GraphQL ::Schema
1015 class BaseObject < GraphQL ::Schema ::Object
1116 end
@@ -46,7 +51,7 @@ def self.authorized?(obj, ctx)
4651 end
4752
4853 def user
49- dataload_record ( ::User , object . user_id )
54+ dataload_record ( ::User , object [ : user_id] )
5055 end
5156 end
5257
@@ -57,7 +62,7 @@ class Book < BaseObject
5762 field :author , "PerfettoSchema::Author"
5863 field :other_book , Book
5964 def reviews
60- object . reviews . limit ( 2 )
65+ object . reviews . limit ( 2 ) . map { | r | { stars : r . stars , user_id : r . user } }
6166 end
6267
6368 def average_review
@@ -105,6 +110,27 @@ def thing(id:)
105110 def crash
106111 raise "Crash the query"
107112 end
113+
114+ class SecretInput < GraphQL ::Schema ::InputObject
115+ argument :password , String
116+ end
117+
118+ class SecretThing < GraphQL ::Schema ::Object
119+ field :greeting , String
120+ end
121+ field :secret_field , SecretThing do
122+ argument :cipher , String , required : false
123+ argument :password , String , required : false
124+ argument :input , [ [ SecretInput ] ] , required : false
125+ end
126+
127+ def secret_field ( cipher : nil , password : nil , input : nil )
128+ {
129+ greeting : "Hello!" ,
130+ cipher : cipher || "FALLBACK_CIPHER" ,
131+ password : password || ( input ? input [ 0 ] [ 0 ] [ :password ] : "FALLBACK_PASSWORD" ) ,
132+ }
133+ end
108134 end
109135
110136 query ( Query )
@@ -159,6 +185,81 @@ def self.detailed_trace?(q)
159185 check_snapshot ( data , "example-rails-#{ Rails ::VERSION ::MAJOR } -#{ Rails ::VERSION ::MINOR } .json" )
160186 end
161187
188+ it "filters params with Rails.application.config.filter_parameters" do
189+ query_str = 'query getStuff { secretField(cipher: "abcdef") { greeting } }'
190+ res = PerfettoSchema . execute ( query_str )
191+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
192+ assert trace_includes? ( json , "abcdef" )
193+ refute trace_includes? ( json , "FILTERED" )
194+
195+ if Rails . application . present?
196+ prev_fp = Rails . application . config . filter_parameters
197+ Rails . application . config . filter_parameters = [ "ciph" ]
198+ else
199+ Rails . application = OpenStruct . new ( config : OpenStruct . new ( filter_parameters : [ "ciph" ] ) )
200+ end
201+ res = PerfettoSchema . execute ( query_str )
202+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
203+ refute trace_includes? ( json , "abcdef" )
204+ assert trace_includes? ( json , "FILTERED" )
205+ ensure
206+ if prev_fp
207+ Rails . application . config . filter_parameters = prev_fp
208+ else
209+ Rails . application = nil
210+ end
211+ end
212+
213+ it "filters params with ActiveSupport" do
214+ query_str = 'query getStuff { secretField(cipher: "abcdef") { greeting } }'
215+ res = PerfettoSchema . execute ( query_str )
216+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
217+ assert trace_includes? ( json , "abcdef" )
218+ refute trace_includes? ( json , "FILTERED" )
219+
220+ query_str = 'query getStuff { secretField(cipher: "abcdef") { greeting } }'
221+ res = PerfettoSchema . execute ( query_str )
222+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
223+ assert trace_includes? ( json , "abcdef" )
224+ refute trace_includes? ( json , "FILTERED" )
225+
226+ if ActiveSupport . respond_to? ( :filter_parameters= )
227+ begin
228+ prev_fp = ActiveSupport . filter_parameters
229+ ActiveSupport . filter_parameters = [ "cipher" ]
230+ res = PerfettoSchema . execute ( query_str )
231+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
232+ refute trace_includes? ( json , "abcdef" )
233+ assert trace_includes? ( json , "[FILTERED]" )
234+
235+ ActiveSupport . filter_parameters = [ "password" ]
236+ res = PerfettoSchema . execute ( 'query getStuff { secretField(input: [[{ password: "jklmn" }]]) { greeting } }' )
237+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
238+ assert trace_includes? ( json , "password" ) , "Name is retained"
239+ refute trace_includes? ( json , "jklmn" ) , "Value is removed"
240+ assert_includes json , "[FILTERED]"
241+ ensure
242+ ActiveSupport . filter_parameters = prev_fp
243+ end
244+ end
245+ end
246+
247+ it "filters params without ActiveSupport" do
248+ query_str = 'query getStuff { secretField(password: "qrstuv") { greeting } }'
249+ res = PerfettoSchema . execute ( query_str , context : { detailed_trace_filter : GraphQL ::Tracing ::PerfettoTrace ::ArgumentsFilter . new } )
250+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
251+ assert trace_includes? ( json , "FILTERED" ) , "The replacement string is present"
252+ assert trace_includes? ( json , "FALLBACK_CIPHER" ) , "Unfiltered values are present"
253+ refute trace_includes? ( json , "qrstuv" ) , "The password is obscured"
254+
255+ query_str = 'query getStuff { secretField(input: [[{ password: "lmnop" }]]) { greeting } }'
256+ res = PerfettoSchema . execute ( query_str , context : { detailed_trace_filter : GraphQL ::Tracing ::PerfettoTrace ::ArgumentsFilter . new } )
257+ json = res . context . query . current_trace . write ( file : nil , debug_json : true )
258+ assert trace_includes? ( json , "password" ) , "Name is retained"
259+ refute trace_includes? ( json , "lmnop" ) , "The password is obscured"
260+ assert trace_includes? ( json , "[FILTERED]" ) , "The replacement string is present"
261+ end
262+
162263 it "provides an error when google-protobuf isn't available" do
163264 stderr_and_stdout , _status = Open3 . capture2e ( %|ruby -e 'require "bundler/inline"; gemfile(true) { source("https://rubygems.org"); gem("graphql", path: "./") }; class MySchema < GraphQL::Schema; trace_with(GraphQL::Tracing::PerfettoTrace); end;'| )
164265 assert_includes stderr_and_stdout , "GraphQL::Tracing::PerfettoTrace can't be used because the `google-protobuf` gem wasn't available. Add it to your project, then try again."
0 commit comments