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
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
2021-01-28 13:52:14 +01:00
# We are caching authorization logic because it is called for each node
# of the requested graph and can be expensive. Context is reset per request so it is safe.
self [ :authorized ] || = Hash . new do | hash , demarche_id |
2023-01-19 17:40:19 +01:00
hash [ demarche_id ] = if self [ :administrateur_id ]
2022-11-30 10:14:23 +01:00
demarche . administrateurs . map ( & :id ) . include? ( self [ :administrateur_id ] )
2023-01-19 17:40:19 +01:00
elsif self [ :token ]
APIToken . find_and_verify ( self [ :token ] , demarche . administrateurs ) . present?
2021-01-28 13:52:14 +01:00
end
end
self [ :authorized ] [ demarche . id ]
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