From 20c1ebef36612d49f0e7181dec2e50bcd5d44382 Mon Sep 17 00:00:00 2001 From: Vithusha Ravirajan Date: Thu, 20 Mar 2025 09:42:37 -0400 Subject: [PATCH 1/7] Warn when custom validators are detected --- lib/graphql/schema/member/has_validators.rb | 6 ++ lib/graphql/schema/validator.rb | 1 + .../validator/custom_validator_warning.rb | 73 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 lib/graphql/schema/validator/custom_validator_warning.rb diff --git a/lib/graphql/schema/member/has_validators.rb b/lib/graphql/schema/member/has_validators.rb index 7e877f9325..8de5472921 100644 --- a/lib/graphql/schema/member/has_validators.rb +++ b/lib/graphql/schema/member/has_validators.rb @@ -10,6 +10,12 @@ module HasValidators # @param validation_config [Hash{Symbol => Hash}] # @return [void] def validates(validation_config) + validation_config.each do |validator_name, _options| + if validator_name.is_a?(Class) || !GraphQL::Schema::Validator.all_validators.key?(validator_name) + GraphQL::Schema::Validator::CustomValidatorWarning.print(validator_name) + end + end + new_validators = GraphQL::Schema::Validator.from_config(self, validation_config) @own_validators ||= [] @own_validators.concat(new_validators) diff --git a/lib/graphql/schema/validator.rb b/lib/graphql/schema/validator.rb index fac5c34511..17723799bd 100644 --- a/lib/graphql/schema/validator.rb +++ b/lib/graphql/schema/validator.rb @@ -171,3 +171,4 @@ def self.validate!(validators, object, context, value, as: nil) GraphQL::Schema::Validator.install(:allow_blank, GraphQL::Schema::Validator::AllowBlankValidator) require "graphql/schema/validator/all_validator" GraphQL::Schema::Validator.install(:all, GraphQL::Schema::Validator::AllValidator) +require "graphql/schema/validator/custom_validator_warning" diff --git a/lib/graphql/schema/validator/custom_validator_warning.rb b/lib/graphql/schema/validator/custom_validator_warning.rb new file mode 100644 index 0000000000..d95fe98268 --- /dev/null +++ b/lib/graphql/schema/validator/custom_validator_warning.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true +module GraphQL + class Schema + class Validator + class CustomValidatorWarning + COLORS = { + cyan: "\e[96m", + red: "\e[91;1m", + magenta: "\e[95m", + green: "\e[92;1m", + reset: "\e[0m" + } + + def self.print(validator_name) + new(validator_name).print + end + + def initialize(validator_name) + @validator_name = validator_name + end + + def print + message = <<~WARNING + #{border} + #{warning_header} + + #{validator_info} + #{risk_warning} + + #{suggestion} + + This warning appears because your schema is using a custom validator. + To disable this warning, set Schema#validate_timeout to a higher value. + #{border} + WARNING + + warn message + warn " #{caller(3, 1).first}" + nil + end + + private + + def border + colorize("*" * 80, :cyan) + end + + def warning_header + colorize("⚠️ WARNING! CUSTOM VALIDATOR DETECTED ⚠️", :red) + end + + def validator_info + "#{colorize('Custom validator:', :cyan)} #{@validator_name}" + end + + def risk_warning + colorize("I/O-based validators may fail unexpectedly due to the default validate_timeout setting.", :magenta) + end + + def suggestion + [ + colorize("If your validator is not performing I/O, consider:", :green), + colorize("- Adjusting validate_timeout in your schema configuration", :green) + ].join("\n") + end + + def colorize(text, color) + "#{COLORS[color]}#{text}#{COLORS[:reset]}" + end + end + end + end +end From 3b1949b0bace5edf35fc2ca7ca056ca6beb0da6f Mon Sep 17 00:00:00 2001 From: Vithusha Ravirajan Date: Thu, 20 Mar 2025 10:13:52 -0400 Subject: [PATCH 2/7] remove text --- lib/graphql/schema/validator/custom_validator_warning.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/graphql/schema/validator/custom_validator_warning.rb b/lib/graphql/schema/validator/custom_validator_warning.rb index d95fe98268..b0c5a8c118 100644 --- a/lib/graphql/schema/validator/custom_validator_warning.rb +++ b/lib/graphql/schema/validator/custom_validator_warning.rb @@ -28,9 +28,6 @@ def print #{risk_warning} #{suggestion} - - This warning appears because your schema is using a custom validator. - To disable this warning, set Schema#validate_timeout to a higher value. #{border} WARNING @@ -46,7 +43,7 @@ def border end def warning_header - colorize("⚠️ WARNING! CUSTOM VALIDATOR DETECTED ⚠️", :red) + colorize("⚠️ CUSTOM VALIDATOR DETECTED ⚠️", :red) end def validator_info From 6069ba305b95f8bfa0a7d18a9e9c819566f12b39 Mon Sep 17 00:00:00 2001 From: Vithusha Ravirajan Date: Thu, 20 Mar 2025 20:28:23 -0400 Subject: [PATCH 3/7] refining warning message --- lib/graphql/schema/member/has_validators.rb | 7 +- lib/graphql/schema/validator.rb | 1 - .../validator/custom_validator_warning.rb | 70 ------------------- 3 files changed, 5 insertions(+), 73 deletions(-) delete mode 100644 lib/graphql/schema/validator/custom_validator_warning.rb diff --git a/lib/graphql/schema/member/has_validators.rb b/lib/graphql/schema/member/has_validators.rb index 8de5472921..1ca94cebf1 100644 --- a/lib/graphql/schema/member/has_validators.rb +++ b/lib/graphql/schema/member/has_validators.rb @@ -12,10 +12,13 @@ module HasValidators def validates(validation_config) validation_config.each do |validator_name, _options| if validator_name.is_a?(Class) || !GraphQL::Schema::Validator.all_validators.key?(validator_name) - GraphQL::Schema::Validator::CustomValidatorWarning.print(validator_name) + warn <<~WARN + WARNING: GraphQL Custom validator '#{validator_name}' detected at #{caller(1,1).first} + Custom validators with I/O operations may fail unexpectedly due to GraphQL's default validate_timeout setting. Long-running I/O operations may not be killed halfway through, resulting in unpredictable behavior. See https://graphql-ruby.org/queries/timeout.html#validation-and-analysis for more information. + WARN end end - + new_validators = GraphQL::Schema::Validator.from_config(self, validation_config) @own_validators ||= [] @own_validators.concat(new_validators) diff --git a/lib/graphql/schema/validator.rb b/lib/graphql/schema/validator.rb index 17723799bd..fac5c34511 100644 --- a/lib/graphql/schema/validator.rb +++ b/lib/graphql/schema/validator.rb @@ -171,4 +171,3 @@ def self.validate!(validators, object, context, value, as: nil) GraphQL::Schema::Validator.install(:allow_blank, GraphQL::Schema::Validator::AllowBlankValidator) require "graphql/schema/validator/all_validator" GraphQL::Schema::Validator.install(:all, GraphQL::Schema::Validator::AllValidator) -require "graphql/schema/validator/custom_validator_warning" diff --git a/lib/graphql/schema/validator/custom_validator_warning.rb b/lib/graphql/schema/validator/custom_validator_warning.rb deleted file mode 100644 index b0c5a8c118..0000000000 --- a/lib/graphql/schema/validator/custom_validator_warning.rb +++ /dev/null @@ -1,70 +0,0 @@ -# frozen_string_literal: true -module GraphQL - class Schema - class Validator - class CustomValidatorWarning - COLORS = { - cyan: "\e[96m", - red: "\e[91;1m", - magenta: "\e[95m", - green: "\e[92;1m", - reset: "\e[0m" - } - - def self.print(validator_name) - new(validator_name).print - end - - def initialize(validator_name) - @validator_name = validator_name - end - - def print - message = <<~WARNING - #{border} - #{warning_header} - - #{validator_info} - #{risk_warning} - - #{suggestion} - #{border} - WARNING - - warn message - warn " #{caller(3, 1).first}" - nil - end - - private - - def border - colorize("*" * 80, :cyan) - end - - def warning_header - colorize("⚠️ CUSTOM VALIDATOR DETECTED ⚠️", :red) - end - - def validator_info - "#{colorize('Custom validator:', :cyan)} #{@validator_name}" - end - - def risk_warning - colorize("I/O-based validators may fail unexpectedly due to the default validate_timeout setting.", :magenta) - end - - def suggestion - [ - colorize("If your validator is not performing I/O, consider:", :green), - colorize("- Adjusting validate_timeout in your schema configuration", :green) - ].join("\n") - end - - def colorize(text, color) - "#{COLORS[color]}#{text}#{COLORS[:reset]}" - end - end - end - end -end From 1624910031d94e97e47fc4f074b0b88e5c5e51f7 Mon Sep 17 00:00:00 2001 From: Vithusha Ravirajan Date: Thu, 20 Mar 2025 20:35:02 -0400 Subject: [PATCH 4/7] add border --- lib/graphql/schema/member/has_validators.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/graphql/schema/member/has_validators.rb b/lib/graphql/schema/member/has_validators.rb index 1ca94cebf1..07e3dcb898 100644 --- a/lib/graphql/schema/member/has_validators.rb +++ b/lib/graphql/schema/member/has_validators.rb @@ -12,9 +12,12 @@ module HasValidators def validates(validation_config) validation_config.each do |validator_name, _options| if validator_name.is_a?(Class) || !GraphQL::Schema::Validator.all_validators.key?(validator_name) + border = "*" * 80 warn <<~WARN + #{border} WARNING: GraphQL Custom validator '#{validator_name}' detected at #{caller(1,1).first} Custom validators with I/O operations may fail unexpectedly due to GraphQL's default validate_timeout setting. Long-running I/O operations may not be killed halfway through, resulting in unpredictable behavior. See https://graphql-ruby.org/queries/timeout.html#validation-and-analysis for more information. + #{border} WARN end end From 4c20f9b4599d9d85780f713dfe9b5991672409a3 Mon Sep 17 00:00:00 2001 From: Vithusha Ravirajan Date: Thu, 20 Mar 2025 20:52:40 -0400 Subject: [PATCH 5/7] moved warning to new file --- lib/graphql/schema/member/has_validators.rb | 8 +------ .../validator/custom_validator_warning.rb | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 lib/graphql/schema/validator/custom_validator_warning.rb diff --git a/lib/graphql/schema/member/has_validators.rb b/lib/graphql/schema/member/has_validators.rb index 07e3dcb898..8902c5cf77 100644 --- a/lib/graphql/schema/member/has_validators.rb +++ b/lib/graphql/schema/member/has_validators.rb @@ -12,13 +12,7 @@ module HasValidators def validates(validation_config) validation_config.each do |validator_name, _options| if validator_name.is_a?(Class) || !GraphQL::Schema::Validator.all_validators.key?(validator_name) - border = "*" * 80 - warn <<~WARN - #{border} - WARNING: GraphQL Custom validator '#{validator_name}' detected at #{caller(1,1).first} - Custom validators with I/O operations may fail unexpectedly due to GraphQL's default validate_timeout setting. Long-running I/O operations may not be killed halfway through, resulting in unpredictable behavior. See https://graphql-ruby.org/queries/timeout.html#validation-and-analysis for more information. - #{border} - WARN + GraphQL::Schema::Validator::CustomValidatorWarning.warn_for(validator_name) end end diff --git a/lib/graphql/schema/validator/custom_validator_warning.rb b/lib/graphql/schema/validator/custom_validator_warning.rb new file mode 100644 index 0000000000..974d704b6d --- /dev/null +++ b/lib/graphql/schema/validator/custom_validator_warning.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module GraphQL + class Schema + class Validator + module CustomValidatorWarning + def self.warn_for(validator_name) + border = "*" * 30 + timestamp = "[#{Time.now.strftime('%Y-%m-%dT%H:%M:%S.%6N')} ##{Process.pid}]" + warn <<~WARN + #{border} + WARNING: GraphQL Custom validator detected: #{validator_name} + Custom validators with I/O operations may fail unexpectedly due to GraphQL's default validate_timeout setting. Long-running I/O operations may not be killed halfway through, resulting in unpredictable behavior. See https://graphql-ruby.org/queries/timeout.html#validation-and-analysis for more information. + #{caller(3,1).first} + #{timestamp} + #{border} + WARN + end + end + end + end +end From 48b91d84bb01cb236379279e38dc3ce8025d4d24 Mon Sep 17 00:00:00 2001 From: Vithusha Ravirajan Date: Thu, 20 Mar 2025 21:01:34 -0400 Subject: [PATCH 6/7] adding require statement --- lib/graphql/schema/validator.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/graphql/schema/validator.rb b/lib/graphql/schema/validator.rb index fac5c34511..17723799bd 100644 --- a/lib/graphql/schema/validator.rb +++ b/lib/graphql/schema/validator.rb @@ -171,3 +171,4 @@ def self.validate!(validators, object, context, value, as: nil) GraphQL::Schema::Validator.install(:allow_blank, GraphQL::Schema::Validator::AllowBlankValidator) require "graphql/schema/validator/all_validator" GraphQL::Schema::Validator.install(:all, GraphQL::Schema::Validator::AllValidator) +require "graphql/schema/validator/custom_validator_warning" From 1c8f5c3ab3c935b4b18877159fe8935f27ec4d1c Mon Sep 17 00:00:00 2001 From: Vithusha Ravirajan Date: Thu, 20 Mar 2025 21:39:37 -0400 Subject: [PATCH 7/7] fix wording --- lib/graphql/schema/validator/custom_validator_warning.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/graphql/schema/validator/custom_validator_warning.rb b/lib/graphql/schema/validator/custom_validator_warning.rb index 974d704b6d..2d3622a335 100644 --- a/lib/graphql/schema/validator/custom_validator_warning.rb +++ b/lib/graphql/schema/validator/custom_validator_warning.rb @@ -9,8 +9,8 @@ def self.warn_for(validator_name) timestamp = "[#{Time.now.strftime('%Y-%m-%dT%H:%M:%S.%6N')} ##{Process.pid}]" warn <<~WARN #{border} - WARNING: GraphQL Custom validator detected: #{validator_name} - Custom validators with I/O operations may fail unexpectedly due to GraphQL's default validate_timeout setting. Long-running I/O operations may not be killed halfway through, resulting in unpredictable behavior. See https://graphql-ruby.org/queries/timeout.html#validation-and-analysis for more information. + WARNING: GraphQL Custom validator registered: #{validator_name} + Note that custom validators with I/O operations may fail unexpectedly due to GraphQL's default validate_timeout setting. Long-running I/O operations may not be killed halfway through, resulting in unpredictable behavior. See https://graphql-ruby.org/queries/timeout.html#validation-and-analysis for more information. #{caller(3,1).first} #{timestamp} #{border}