Better graphql mutation error messages

This commit is contained in:
Paul Chavard 2020-12-10 16:23:24 +01:00
parent cdb9d99eb2
commit 65d650eba6
9 changed files with 106 additions and 69 deletions

View file

@ -1,16 +1,24 @@
module Mutations module Mutations
class BaseMutation < GraphQL::Schema::RelayClassicMutation class BaseMutation < GraphQL::Schema::RelayClassicMutation
private
def validate_blob(blob_id) def validate_blob(blob_id)
if blob_id.present? begin
begin blob = ActiveStorage::Blob.find_signed(blob_id)
blob = ActiveStorage::Blob.find_signed(blob_id) blob.identify
blob.identify true
nil rescue ActiveStorage::FileNotFoundError
rescue ActiveStorage::FileNotFoundError return false, { errors: ['Le fichier na pas été correctement téléversé sur le serveur de stockage'] }
return { errors: ['Le fichier na pas été correctement téléversé sur le serveur de stockage'] } rescue ActiveSupport::MessageVerifier::InvalidSignature
rescue ActiveSupport::MessageVerifier::InvalidSignature return false, { errors: ['Le hash du fichier téléversé est invalide'] }
return { errors: ['Lidentifiant du fichier téléversé est invalide'] } end
end end
def dossier_authorized_for?(dossier, instructeur)
if instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
true
else
return false, { errors: ['Linstructeur na pas les droits daccès à ce dossier'] }
end end
end end
end end

View file

@ -13,21 +13,25 @@ module Mutations
field :errors, [Types::ValidationErrorType], null: true field :errors, [Types::ValidationErrorType], null: true
def resolve(dossier:, instructeur:, motivation: nil, justificatif: nil) def resolve(dossier:, instructeur:, motivation: nil, justificatif: nil)
if dossier.en_instruction? dossier.accepter!(instructeur, motivation, justificatif)
errors = validate_blob(justificatif)
if errors
return errors
end
dossier.accepter!(instructeur, motivation, justificatif)
{ dossier: dossier } { dossier: dossier }
end
def ready?(justificatif: nil, **args)
if justificatif.present?
validate_blob(justificatif)
else else
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] } true
end end
end end
def authorized?(dossier:, instructeur:, motivation: nil, justificatif: nil) def authorized?(dossier:, instructeur:, **args)
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id) if !dossier.en_instruction?
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
end
dossier_authorized_for?(dossier, instructeur)
end end
end end
end end

View file

@ -9,17 +9,17 @@ module Mutations
field :errors, [Types::ValidationErrorType], null: true field :errors, [Types::ValidationErrorType], null: true
def resolve(dossier:, instructeur:) def resolve(dossier:, instructeur:)
if dossier.termine? dossier.archiver!(instructeur)
dossier.archiver!(instructeur)
{ dossier: dossier } { dossier: dossier }
else
{ errors: ["Un dossier ne peut être archivé quune fois le traitement terminé"] }
end
end end
def authorized?(dossier:, instructeur:) def authorized?(dossier:, instructeur:)
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id) if !dossier.termine?
return false, { errors: ["Un dossier ne peut être archivé quune fois le traitement terminé"] }
end
dossier_authorized_for?(dossier, instructeur)
end end
end end
end end

View file

@ -11,16 +11,19 @@ module Mutations
field :errors, [Types::ValidationErrorType], null: true field :errors, [Types::ValidationErrorType], null: true
def resolve(dossier:, groupe_instructeur:) def resolve(dossier:, groupe_instructeur:)
if dossier.groupe_instructeur == groupe_instructeur dossier.update!(groupe_instructeur: groupe_instructeur)
{ errors: ["Le dossier est déjà avec le grope instructeur: '#{groupe_instructeur.label}'"] }
else { dossier: dossier }
dossier.update!(groupe_instructeur: groupe_instructeur)
{ dossier: dossier }
end
end end
def authorized?(dossier:, groupe_instructeur:) def authorized?(dossier:, groupe_instructeur:)
dossier.groupe_instructeur.procedure == groupe_instructeur.procedure if dossier.groupe_instructeur == groupe_instructeur
return false, { errors: ["Le dossier est déjà avec le grope instructeur: '#{groupe_instructeur.label}'"] }
elsif dossier.groupe_instructeur.procedure != groupe_instructeur.procedure
return false, { errors: ["Le groupe instructeur '#{groupe_instructeur.label}' nappartient pas à la même démarche que le dossier"] }
else
true
end
end end
end end
end end

View file

@ -13,21 +13,24 @@ module Mutations
field :errors, [Types::ValidationErrorType], null: true field :errors, [Types::ValidationErrorType], null: true
def resolve(dossier:, instructeur:, motivation:, justificatif: nil) def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
if dossier.en_instruction? dossier.classer_sans_suite!(instructeur, motivation, justificatif)
errors = validate_blob(justificatif)
if errors
return errors
end
dossier.classer_sans_suite!(instructeur, motivation, justificatif)
{ dossier: dossier } { dossier: dossier }
end
def ready?(justificatif: nil, **args)
if justificatif.present?
validate_blob(justificatif)
else else
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] } true
end end
end end
def authorized?(dossier:, instructeur:, motivation:, justificatif: nil) def authorized?(dossier:, instructeur:, **args)
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id) if !dossier.en_instruction?
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
end
dossier_authorized_for?(dossier, instructeur)
end end
end end
end end

View file

@ -11,10 +11,6 @@ module Mutations
field :errors, [Types::ValidationErrorType], null: true field :errors, [Types::ValidationErrorType], null: true
def resolve(dossier:, instructeur:, body:, attachment: nil) def resolve(dossier:, instructeur:, body:, attachment: nil)
errors = validate_blob(attachment)
if errors
return errors
end
message = CommentaireService.build(instructeur, dossier, body: body, piece_jointe: attachment) message = CommentaireService.build(instructeur, dossier, body: body, piece_jointe: attachment)
if message.save if message.save
@ -24,8 +20,16 @@ module Mutations
end end
end end
def authorized?(dossier:, instructeur:, body:, attachment: nil) def ready?(attachment: nil, **args)
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id) if attachment.present?
validate_blob(attachment)
else
true
end
end
def authorized?(dossier:, instructeur:, **args)
dossier_authorized_for?(dossier, instructeur)
end end
end end
end end

View file

@ -11,17 +11,16 @@ module Mutations
field :errors, [Types::ValidationErrorType], null: true field :errors, [Types::ValidationErrorType], null: true
def resolve(dossier:, instructeur:) def resolve(dossier:, instructeur:)
if dossier.en_construction? dossier.passer_en_instruction!(instructeur)
dossier.passer_en_instruction!(instructeur)
{ dossier: dossier } { dossier: dossier }
else
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
end
end end
def authorized?(dossier:, instructeur:) def authorized?(dossier:, instructeur:)
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id) if !dossier.en_construction?
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
end
dossier_authorized_for?(dossier, instructeur)
end end
end end
end end

View file

@ -13,21 +13,24 @@ module Mutations
field :errors, [Types::ValidationErrorType], null: true field :errors, [Types::ValidationErrorType], null: true
def resolve(dossier:, instructeur:, motivation:, justificatif: nil) def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
if dossier.en_instruction? dossier.refuser!(instructeur, motivation, justificatif)
errors = validate_blob(justificatif)
if errors
return errors
end
dossier.refuser!(instructeur, motivation, justificatif)
{ dossier: dossier } { dossier: dossier }
end
def ready?(justificatif: nil, **args)
if justificatif.present?
validate_blob(justificatif)
else else
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] } true
end end
end end
def authorized?(dossier:, instructeur:, motivation:, justificatif: nil) def authorized?(dossier:, instructeur:, **args)
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id) if !dossier.en_instruction?
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
end
dossier_authorized_for?(dossier, instructeur)
end end
end end
end end

View file

@ -627,7 +627,7 @@ describe API::V2::GraphqlController do
it "should fail" do it "should fail" do
expect(gql_errors).to eq(nil) expect(gql_errors).to eq(nil)
expect(gql_data).to eq(dossierEnvoyerMessage: { expect(gql_data).to eq(dossierEnvoyerMessage: {
errors: [{ message: "Lidentifiant du fichier téléversé est invalide" }], errors: [{ message: "Le hash du fichier téléversé est invalide" }],
message: nil message: nil
}) })
end end
@ -636,11 +636,12 @@ describe API::V2::GraphqlController do
describe 'dossierPasserEnInstruction' do describe 'dossierPasserEnInstruction' do
let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) } let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) }
let(:instructeur_id) { instructeur.to_typed_id }
let(:query) do let(:query) do
"mutation { "mutation {
dossierPasserEnInstruction(input: { dossierPasserEnInstruction(input: {
dossierId: \"#{dossier.to_typed_id}\", dossierId: \"#{dossier.to_typed_id}\",
instructeurId: \"#{instructeur.to_typed_id}\" instructeurId: \"#{instructeur_id}\"
}) { }) {
dossier { dossier {
id id
@ -680,6 +681,18 @@ describe API::V2::GraphqlController do
}) })
end end
end end
context 'instructeur error' do
let(:instructeur_id) { create(:instructeur).to_typed_id }
it "should fail" do
expect(gql_errors).to eq(nil)
expect(gql_data).to eq(dossierPasserEnInstruction: {
errors: [{ message: 'Linstructeur na pas les droits daccès à ce dossier' }],
dossier: nil
})
end
end
end end
describe 'dossierClasserSansSuite' do describe 'dossierClasserSansSuite' do