demarches-normaliennes/app/graphql/api/v2/context.rb
2024-08-22 09:26:48 +02:00

112 lines
3 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
class API::V2::Context < GraphQL::Query::Context
# This method is used to check if a given fragment is used in the given query. We need that in
# order to maintain backward compatibility for Types de Champ that we extended in later iterations
# of our schema. If it is an introspection query, we assume all fragments are present.
def has_fragment?(fragment_name)
return true if query.nil?
return true if introspection?
self[:has_fragment] ||= Hash.new do |hash, fragment_name|
visitor = HasFragment.new(query.document, fragment_name)
visitor.visit
hash[fragment_name] = visitor.found
end
self[:has_fragment][fragment_name]
end
def has_fragments?(fragment_names)
fragment_names.any? { has_fragment?(_1) }
end
def introspection?
query.selected_operation.name == "IntrospectionQuery"
end
def internal_use?
self[:internal_use]
end
def write_access?
self[:write_access]
end
def current_administrateur
unless self[:administrateur_id]
raise GraphQL::ExecutionError.new("Pour effectuer cette opération, vous avez besoin dun jeton au nouveau format. Vous pouvez lobtenir dans votre interface administrateur.", extensions: { code: :deprecated_token })
end
Administrateur.find(self[:administrateur_id])
end
def authorized_demarche?(demarche, opendata: false)
if internal_use?
return true
end
if opendata && demarche.opendata?
return true
end
self[:authorized] ||= {}
if self[:authorized][demarche.id].nil?
self[:authorized][demarche.id] = compute_demarche_authorization(demarche)
end
self[:authorized][demarche.id]
end
def query_info
{
graphql_query: query.query_string,
graphql_variables: query.provided_variables&.to_json,
graphql_mutation: mutation?,
graphql_null_error: errors.any? { _1.is_a? GraphQL::InvalidNullError }.presence,
graphql_timeout_error: errors.any? { _1.is_a? GraphQL::Schema::Timeout::TimeoutError }.presence,
graphql_api_token_id: self[:api_token_id]
}.compact
end
private
def mutation?
query.lookahead.selections.any? { _1.field.type.respond_to?(:mutation) }.presence
rescue
false
end
def compute_demarche_authorization(demarche)
# procedure_ids and token are passed from graphql controller
self[:procedure_ids].include?(demarche.id)
end
# This is a query AST visitor that we use to check
# if a fragment with a given name is used in the given document.
# We check for both inline and standalone fragments.
class HasFragment < GraphQL::Language::Visitor
def initialize(document, fragment_name)
super(document)
@fragment_name = fragment_name.to_s
@found = false
end
attr_reader :found
def on_inline_fragment(node, parent)
if node.type.name == @fragment_name
@found = true
end
super
end
def on_fragment_definition(node, parent)
if node.type.name == @fragment_name
@found = true
end
super
end
end
end