2024-04-29 00:17:15 +02:00
# frozen_string_literal: true
2020-08-05 18:40:47 +02:00
class API :: V2 :: Context < GraphQL :: Query :: Context
2023-01-19 19:37:58 +01:00
# 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.
2022-04-11 22:35:51 +02:00
def has_fragment? ( fragment_name )
2023-01-19 19:37:58 +01:00
return true if query . nil?
return true if introspection?
2022-04-11 22:35:51 +02:00
self [ :has_fragment ] || = Hash . new do | hash , fragment_name |
visitor = HasFragment . new ( query . document , fragment_name )
2020-12-18 11:16:18 +01:00
visitor . visit
2022-04-11 22:35:51 +02:00
hash [ fragment_name ] = visitor . found
2020-12-18 11:16:18 +01:00
end
2022-04-11 22:35:51 +02:00
self [ :has_fragment ] [ fragment_name ]
2020-12-18 11:16:18 +01:00
end
2023-01-19 19:37:58 +01:00
def has_fragments? ( fragment_names )
fragment_names . any? { has_fragment? ( _1 ) }
end
def introspection?
query . selected_operation . name == " IntrospectionQuery "
end
2021-01-28 13:52:14 +01:00
def internal_use?
self [ :internal_use ]
end
2023-02-13 14:25:17 +01:00
def write_access?
self [ :write_access ]
end
2022-11-24 15:25:14 +01:00
def current_administrateur
unless self [ :administrateur_id ]
2023-01-10 17:20:22 +01:00
raise GraphQL :: ExecutionError . new ( " Pour effectuer cette opération, vous avez besoin d’ un jeton au nouveau format. Vous pouvez l’ obtenir dans votre interface administrateur. " , extensions : { code : :deprecated_token } )
2022-11-24 15:25:14 +01:00
end
Administrateur . find ( self [ :administrateur_id ] )
end
2022-11-25 13:33:10 +01:00
def authorized_demarche? ( demarche , opendata : false )
2021-01-28 13:52:14 +01:00
if internal_use?
return true
end
2022-11-25 13:33:10 +01:00
if opendata && demarche . opendata?
return true
end
2023-02-21 16:06:39 +01:00
self [ :authorized ] || = { }
if self [ :authorized ] [ demarche . id ] . nil?
2023-03-01 17:47:38 +01:00
self [ :authorized ] [ demarche . id ] = compute_demarche_authorization ( demarche )
2021-01-28 13:52:14 +01:00
end
self [ :authorized ] [ demarche . id ]
end
2023-04-04 14:45:22 +02:00
def query_info
{
graphql_query : query . query_string ,
graphql_variables : query . provided_variables & . to_json ,
2023-08-02 10:54:03 +02:00
graphql_mutation : mutation? ,
2023-04-04 14:45:22 +02:00
graphql_null_error : errors . any? { _1 . is_a? GraphQL :: InvalidNullError } . presence ,
2023-11-08 11:21:45 +01:00
graphql_timeout_error : errors . any? { _1 . is_a? GraphQL :: Schema :: Timeout :: TimeoutError } . presence ,
graphql_api_token_id : self [ :api_token_id ]
2023-04-04 14:45:22 +02:00
} . compact
end
2023-03-01 17:47:38 +01:00
private
2023-08-02 10:54:03 +02:00
def mutation?
query . lookahead . selections . any? { _1 . field . type . respond_to? ( :mutation ) } . presence
rescue
false
end
2023-03-01 17:47:38 +01:00
def compute_demarche_authorization ( demarche )
# procedure_ids and token are passed from graphql controller
2023-08-03 16:33:30 +02:00
self [ :procedure_ids ] . include? ( demarche . id )
2023-03-01 17:47:38 +01:00
end
2022-04-11 22:35:51 +02:00
# 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.
2020-12-18 11:16:18 +01:00
class HasFragment < GraphQL :: Language :: Visitor
2022-04-11 22:35:51 +02:00
def initialize ( document , fragment_name )
2020-12-18 11:16:18 +01:00
super ( document )
2022-04-11 22:35:51 +02:00
@fragment_name = fragment_name . to_s
2020-12-18 11:16:18 +01:00
@found = false
end
attr_reader :found
def on_inline_fragment ( node , parent )
2022-04-11 22:35:51 +02:00
if node . type . name == @fragment_name
@found = true
end
super
end
def on_fragment_definition ( node , parent )
if node . type . name == @fragment_name
2020-12-18 11:16:18 +01:00
@found = true
end
super
end
end
end