Skip to content

Commit fe43033

Browse files
committed
feat(tiptap): reject mentions of tags unavailable for the template state
Legacy text validation implicitly rejected a tag not available for the template's DOSSIER_STATE (its libelle simply didn't resolve), but a tiptap mention carries its tag id verbatim and slipped through. Check non-champ mention ids against the state-filtered catalog, for mail templates and attestations v2 alike. The attestation v2 factory carried individual mentions on a non-individual procedure — content the UI cannot produce and that this validation now rejects; it uses an identity-agnostic tag instead.
1 parent 425b5d5 commit fe43033

4 files changed

Lines changed: 49 additions & 4 deletions

File tree

app/models/concerns/tags_substitution_concern.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,19 @@ def used_type_de_champ_tags(text_or_tiptap)
287287
used_tags_and_libelle_for(text_or_tiptap.to_s)
288288
end
289289

290+
available_ids = nil
291+
290292
used_tags.filter_map do |(tag, libelle)|
291293
if tag.nil?
292294
[libelle]
293295
elsif !tag.in?(SHARED_TAG_IDS) && tag.start_with?('tdc')
294296
[libelle, tag.gsub(/^tdc/, '').to_i]
297+
else
298+
# A tiptap mention carries its tag id verbatim, so ids of tags unknown or
299+
# not available for this template's DOSSIER_STATE must be rejected here —
300+
# the legacy text parsing did it implicitly (the libelle didn't resolve).
301+
available_ids ||= procedure_types_de_champ_tags.map { _1[:id] }
302+
[libelle] unless tag.in?(available_ids)
295303
end
296304
end
297305
end

spec/factories/attestation_template.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@
4040
{
4141
"type" => "paragraph",
4242
"content" => [
43-
{ "text" => "Nom: ", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "individual_last_name", "label" => "prénom" } }, { "text" => " ", "type" => "text" },
44-
{ "type" => "mention", "attrs" => { "id" => "individual_first_name", "label" => "nom" } }, { "text" => " ", "type" => "text" },
43+
{ "text" => "Déposé le : ", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "dossier_depose_at", "label" => "date de dépôt" } }, { "text" => " ", "type" => "text" },
4544
],
4645
},
4746
],

spec/models/attestation_template_spec.rb

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,25 @@
227227
end
228228

229229
context 'body v2' do
230-
let(:attestation) { create(:attestation_template, :v2) }
231-
let(:dossier) { create(:dossier, procedure: attestation.procedure, individual: build(:individual, nom: 'Doe', prenom: 'John')) }
230+
let(:procedure) { create(:procedure, :for_individual) }
231+
let(:attestation) do
232+
create(:attestation_template, :v2, procedure:, json_body: {
233+
"type" => "doc",
234+
"content" => [
235+
{ "type" => "title", "attrs" => { "textAlign" => "center" }, "content" => [{ "text" => "Mon titre pour ", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "dossier_procedure_libelle", "label" => "libellé démarche" } }] },
236+
{
237+
"type" => "paragraph",
238+
"content" => [
239+
{ "text" => "Nom: ", "type" => "text" },
240+
{ "type" => "mention", "attrs" => { "id" => "individual_last_name", "label" => "nom" } },
241+
{ "text" => " ", "type" => "text" },
242+
{ "type" => "mention", "attrs" => { "id" => "individual_first_name", "label" => "prénom" } },
243+
],
244+
},
245+
],
246+
})
247+
end
248+
let(:dossier) { create(:dossier, procedure:, individual: build(:individual, nom: 'Doe', prenom: 'John')) }
232249

233250
it do
234251
body = attestation.render_attributes_for(dossier: dossier)[:body]

spec/models/concerns/mail_template_concern_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,5 +326,26 @@
326326
expect(mail).not_to be_valid
327327
expect(mail.errors[:body]).to be_present
328328
end
329+
330+
it 'invalide une mention d’une balise indisponible pour l’état du template (parité legacy)' do
331+
decision_mention = {
332+
"type" => "doc",
333+
"content" => [
334+
{
335+
"type" => "paragraph", "content" => [
336+
{ "type" => "mention", "attrs" => { "id" => "dossier_processed_at", "label" => "date de décision" } },
337+
],
338+
},
339+
],
340+
}
341+
342+
mail.json_body = decision_mention
343+
expect(mail).not_to be_valid
344+
expect(mail.errors[:json_body]).to be_present
345+
346+
closed_mail = Mails::ClosedMail.default_for_procedure(procedure)
347+
closed_mail.json_body = decision_mention
348+
expect(closed_mail).to be_valid
349+
end
329350
end
330351
end

0 commit comments

Comments
 (0)