Merge pull request #11073 from demarches-simplifiees/confirm_FC_email

ETQ Usager, mon email est dit fiable lorsque qu'il provient de FC et que je l'ai visuellement vérifié
This commit is contained in:
LeSim 2024-12-13 10:46:05 +00:00 committed by GitHub
commit 3ee386e1d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 178 additions and 130 deletions

View file

@ -59,12 +59,11 @@ class FranceConnect::ParticulierController < ApplicationController
def merge_using_fc_email def merge_using_fc_email
@fci.safely_associate_user!(@fci.email_france_connect) @fci.safely_associate_user!(@fci.email_france_connect)
@fci.user.update!(email_verified_at: Time.current)
sign_in(@fci.user) sign_in(@fci.user)
@fci.send_custom_confirmation_instructions redirect_to destination_path(@fci.user), notice: t('france_connect.particulier.flash.connection_done', application_name: Current.application_name)
render :confirmation_sent, locals: { email: @fci.email_france_connect, destination_path: destination_path(@fci.user) }
end end
def merge_using_password def merge_using_password

View file

@ -1,33 +1,63 @@
import { ApplicationController } from './application_controller'; import { ApplicationController } from './application_controller';
export class EmailFranceConnectController extends ApplicationController { export class EmailFranceConnectController extends ApplicationController {
static targets = ['useFranceConnectEmail', 'emailField']; static targets = [
'useFranceConnectEmail',
'emailField',
'submit',
'emailInput',
'form'
];
emailFieldTarget!: HTMLElement; emailFieldTarget!: HTMLElement;
useFranceConnectEmailTargets!: HTMLInputElement[]; useFranceConnectEmailTargets!: HTMLInputElement[];
submitTarget!: HTMLButtonElement;
emailInputTarget!: HTMLInputElement;
formTarget!: HTMLFormElement;
connect() { fcEmailPathValue!: string;
this.triggerEmailField(); customEmailPathValue!: string;
}
static values = {
fcEmailPath: String,
customEmailPath: String
};
triggerEmailField() { triggerEmailField() {
const checkedTarget = this.useFranceConnectEmailTargets.find( if (this.useFCEmail()) {
(target) => target.checked
);
const inputElement = this.emailFieldTarget.querySelector(
'input[type="email"]'
) as HTMLInputElement;
if (checkedTarget && checkedTarget.value === 'false') {
this.emailFieldTarget.classList.remove('hidden');
this.emailFieldTarget.setAttribute('aria-hidden', 'false');
inputElement.setAttribute('required', '');
} else {
this.emailFieldTarget.classList.add('hidden'); this.emailFieldTarget.classList.add('hidden');
this.emailFieldTarget.setAttribute('aria-hidden', 'true'); this.emailFieldTarget.setAttribute('aria-hidden', 'true');
inputElement.removeAttribute('required');
inputElement.value = ''; this.emailInputTarget.removeAttribute('required');
this.emailInputTarget.value = '';
this.formTarget.action = this.fcEmailPathValue;
} else {
this.emailFieldTarget.classList.remove('hidden');
this.emailFieldTarget.setAttribute('aria-hidden', 'false');
this.emailInputTarget.setAttribute('required', '');
this.formTarget.action = this.customEmailPathValue;
} }
} }
triggerSubmitDisabled() {
if (this.useFCEmail() || this.isEmailInputFilled()) {
this.submitTarget.disabled = false;
} else {
this.submitTarget.disabled = true;
}
}
useFCEmail() {
return (
this.useFranceConnectEmailTargets.find((target) => target.checked)
?.value === 'true' || false
);
}
isEmailInputFilled() {
return this.emailInputTarget.value.length > 0;
}
} }

View file

@ -9,26 +9,52 @@
%p= t('.use_email_for_notifications') %p= t('.use_email_for_notifications')
%fieldset.fr-fieldset %fieldset.fr-fieldset
= form_with url: france_connect_particulier_merge_using_fc_email_path(merge_token: @fci.merge_token), method: :post, data: { controller: 'email-france-connect' } do |f| = form_with url: france_connect_particulier_merge_using_fc_email_path,
method: :post,
data: { controller: 'email-france-connect',
email_france_connect_fc_email_path_value: france_connect_particulier_merge_using_fc_email_path,
email_france_connect_custom_email_path_value: france_connect_particulier_send_email_merge_request_path,
email_france_connect_target: "form" } do |f|
= hidden_field_tag :merge_token, @fci.merge_token = hidden_field_tag :merge_token, @fci.merge_token
%fieldset.fr-fieldset %fieldset.fr-fieldset
%legend.fr-fieldset__legend %legend.fr-fieldset__legend
.fr-fieldset__element .fr-fieldset__element
.fr-radio-group .fr-radio-group
= f.radio_button :use_france_connect_email, true, id: 'use_france_connect_email_yes', class: 'fr-radio', required: true, data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } = f.radio_button :use_france_connect_email, true,
id: 'use_france_connect_email_yes',
class: 'fr-radio',
required: true,
data: { action: "email-france-connect#triggerEmailField email-france-connect#triggerSubmitDisabled",
email_france_connect_target: "useFranceConnectEmail" }
%label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_yes' } %label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_yes' }
= t('.keep_fc_email_html', email: h(@fci.email_france_connect)).html_safe = t('.keep_fc_email_html', email: h(@fci.email_france_connect))
.fr-fieldset__element .fr-fieldset__element
.fr-radio-group .fr-radio-group
= f.radio_button :use_france_connect_email, false, id: 'use_france_connect_email_no', class: 'fr-radio', required: true, data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } = f.radio_button :use_france_connect_email, false,
id: 'use_france_connect_email_no',
class: 'fr-radio',
required: true,
data: { action: "email-france-connect#triggerEmailField email-france-connect#triggerSubmitDisabled", email_france_connect_target: "useFranceConnectEmail" }
%label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_no' } %label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_no' }
= t('.use_another_email') = t('.use_another_email')
.fr-fieldset__element.fr-fieldset__element--inline.hidden{ aria: { hidden: true }, data: { email_france_connect_target: "emailField", controller: 'email-input', email_input_url_value: show_email_suggestions_path } } .fr-fieldset__element.fr-fieldset__element--inline.hidden{
aria: { hidden: true },
data: {
email_france_connect_target: "emailField",
controller: 'email-input',
email_input_url_value: show_email_suggestions_path
}
}
= f.label :email, t('.alternative_email'), class: "fr-label" = f.label :email, t('.alternative_email'), class: "fr-label"
%span.fr-hint-text.mb-1= t('activerecord.attributes.user.hints.email') %span.fr-hint-text.mb-1= t('activerecord.attributes.user.hints.email')
= f.email_field :email, class: "fr-input" = f.email_field :email,
data: { action: "email-france-connect#triggerSubmitDisabled", email_france_connect_target: "emailInput" },
class: "fr-input"
.suspect-email.hidden{ data: { "email-input-target": 'ariaRegion'}, aria: { live: 'off' } } .suspect-email.hidden{ data: { "email-input-target": 'ariaRegion'}, aria: { live: 'off' } }
= render Dsfr::AlertComponent.new(title: t('utils.email_suggest.wanna_say'), state: :info, heading_level: :div) do |c| = render Dsfr::AlertComponent.new(title: t('utils.email_suggest.wanna_say'), state: :info, heading_level: :div) do |c|
@ -40,4 +66,7 @@
= button_tag type: 'button', class: 'fr-btn fr-btn--sm', data: { action: 'click->email-input#discard'} do = button_tag type: 'button', class: 'fr-btn fr-btn--sm', data: { action: 'click->email-input#discard'} do
= t('utils.no') = t('utils.no')
%div %div
= f.submit t('.confirm'), class: 'fr-btn' = f.submit t('.confirm'),
class: 'fr-btn',
data: { email_france_connect_target: "submit" },
disabled: true

View file

@ -1,12 +0,0 @@
.fr-container
.fr-col-12.fr-col-md-6.fr-col-offset-md-3
%h1.fr-mt-6w.fr-h2.center= t('.confirmation_sent_by_email')
%p.center= image_tag("user/confirmation-email.svg", alt: '')
= render Dsfr::AlertComponent.new(title: '', state: :info, heading_level: 'h2', extra_class_names: 'fr-mt-6w fr-mb-3w') do |c|
- c.with_body do
%p= t('.intro_html', email: h(email)).html_safe
%p= t('.click_the_link_in_the_email')
%p.center= link_to t('.continue'), destination_path, class: 'fr-btn'

View file

@ -888,11 +888,6 @@ en:
alternative_email: "Please provide the email to use for contacting you." alternative_email: "Please provide the email to use for contacting you."
keep_fc_email_html: Yes, use <b class='bold'>%{email}</b> as contact email. keep_fc_email_html: Yes, use <b class='bold'>%{email}</b> as contact email.
use_another_email: No, use another address. use_another_email: No, use another address.
confirmation_sent:
confirmation_sent_by_email: "Confirm your email"
intro_html: "A confirmation email has been sent to your address <span class='fr-badge fr-badge--info fr-badge--no-icon fr-badge--lowercase'>%{email}</span>"
click_the_link_in_the_email: "Please click the link in the email to confirm your account and connect with France Connect in the future."
continue: "Continue"
merge: merge:
title: "Merge your account FranceConnect and %{application_name}" title: "Merge your account FranceConnect and %{application_name}"
subtitle_html: "Hello,<br /><br />Your account FranceConnect uses <b class='bold'>%{email}</b> as contact email.<br />But there is an existing %{application_name} account using this email." subtitle_html: "Hello,<br /><br />Your account FranceConnect uses <b class='bold'>%{email}</b> as contact email.<br />But there is an existing %{application_name} account using this email."

View file

@ -100,7 +100,7 @@ fr:
line_three: "75007 PARIS" line_three: "75007 PARIS"
direction: "Direction de la publication" direction: "Direction de la publication"
direction_content: "Madame Stéphanie Schaer, Directrice interministérielle du numérique." direction_content: "Madame Stéphanie Schaer, Directrice interministérielle du numérique."
hosting: "Prestataire d'hébergement" hosting: "Prestataire dhébergement"
hosting_content: hosting_content:
firm: "OVH" firm: "OVH"
RCS_term: "RCS" RCS_term: "RCS"
@ -120,12 +120,12 @@ fr:
content_html: "Le site Démarches simplifiées est <strong>partiellement conforme</strong> au <a href=\"https://accessibilite.numerique.gouv.fr/\">Référentiel Général dAmélioration de lAccessibilité (RGAA)</a> version 4.1.2 en raison des non-conformités listées ci-après." content_html: "Le site Démarches simplifiées est <strong>partiellement conforme</strong> au <a href=\"https://accessibilite.numerique.gouv.fr/\">Référentiel Général dAmélioration de lAccessibilité (RGAA)</a> version 4.1.2 en raison des non-conformités listées ci-après."
results: results:
title: "Résultats des tests" title: "Résultats des tests"
content: "L'audit réalisé en interne en juin 2023 révèle que le taux de conformité global est de 81,36% sur l'échantillon de pages analysés." content: "Laudit réalisé en interne en juin 2023 révèle que le taux de conformité global est de 81,36% sur léchantillon de pages analysés."
programme: programme:
intro: "Les usagers peuvent suivre les mesures engagées par le service pour améliorer laccessibilité du site grâce au " intro: "Les usagers peuvent suivre les mesures engagées par le service pour améliorer laccessibilité du site grâce au "
label: "programme d'amélioration continue de DS en matière d'accessibilité" label: "programme damélioration continue de DS en matière daccessibilité"
url: "https://github.com/demarches-simplifiees/demarches-simplifiees.fr/issues?q=accessibilit%C3%A9+" url: "https://github.com/demarches-simplifiees/demarches-simplifiees.fr/issues?q=accessibilit%C3%A9+"
title: "programme d'amélioration continue de DS en matière d'accessibilité - nouvel onglet" title: "programme damélioration continue de DS en matière daccessibilité - nouvel onglet"
no_accessible: no_accessible:
title: "Contenus non accessibles" title: "Contenus non accessibles"
subtitle_one: "Non-conformités" subtitle_one: "Non-conformités"
@ -145,7 +145,7 @@ fr:
</ul>" </ul>"
subtitle_two: "Remarques complémentaires" subtitle_two: "Remarques complémentaires"
content_html: "<p class=\"fr-mb-2w\">Les pages de documentation sont gérées par un outil tiers. Elles ne sont pas entièrement accessibles.</p> content_html: "<p class=\"fr-mb-2w\">Les pages de documentation sont gérées par un outil tiers. Elles ne sont pas entièrement accessibles.</p>
<p class=\"fr-mb-2w\">La gestion de la FAQ était déléguée à un outil tiers. Elle a été réintégrée à la plateforme en mai 2024 et n'a pas encore été auditée.</p>" <p class=\"fr-mb-2w\">La gestion de la FAQ était déléguée à un outil tiers. Elle a été réintégrée à la plateforme en mai 2024 et na pas encore été auditée.</p>"
preparation: preparation:
title: "Établissement de cette déclaration daccessibilité" title: "Établissement de cette déclaration daccessibilité"
@ -194,11 +194,11 @@ fr:
adress_html: "Par voie postale : DINUM , 20 avenue de Ségur 75007 Paris" adress_html: "Par voie postale : DINUM , 20 avenue de Ségur 75007 Paris"
remedies: remedies:
title: "Voies de recours" title: "Voies de recours"
line_one: "Si vous constatez un défaut daccessibilité vous empêchant daccéder à un contenu ou une fonctionnalité du site, que vous nous le signalez et que vous ne parvenez pas à obtenir une réponse rapide de notre part, vous êtes en droit de contacter l'Arcom ou de saisir le Défenseur des droits." line_one: "Si vous constatez un défaut daccessibilité vous empêchant daccéder à un contenu ou une fonctionnalité du site, que vous nous le signalez et que vous ne parvenez pas à obtenir une réponse rapide de notre part, vous êtes en droit de contacter lArcom ou de saisir le Défenseur des droits."
arcom_title: "Contacter l'Arcom" arcom_title: "Contacter lArcom"
arcom_content_html: "Afin de signaler un ou plusieurs manquement(s) à la réglementation relative à laccessibilité numérique, rendez-vous sur le <a href=\"https://www.arcom.fr/contact\">formulaire de contact du site web de l'Arcom</a>." arcom_content_html: "Afin de signaler un ou plusieurs manquement(s) à la réglementation relative à laccessibilité numérique, rendez-vous sur le <a href=\"https://www.arcom.fr/contact\">formulaire de contact du site web de lArcom</a>."
ddd_title: "Saisir le Défenseur des droits" ddd_title: "Saisir le Défenseur des droits"
ddd_intro: "Pour faire valoir vos droits relatifs à des défauts d'accessibilité que vous avez rencontrés, plusieurs moyens sont à votre disposition :" ddd_intro: "Pour faire valoir vos droits relatifs à des défauts daccessibilité que vous avez rencontrés, plusieurs moyens sont à votre disposition :"
remedies_one: remedies_one:
label: "Un formulaire de contact" label: "Un formulaire de contact"
url: "https://www.defenseurdesdroits.fr/nous-contacter" url: "https://www.defenseurdesdroits.fr/nous-contacter"
@ -208,14 +208,14 @@ fr:
label: "Contacter le délégué du Défenseur des droits dans votre région" label: "Contacter le délégué du Défenseur des droits dans votre région"
url: "https://www.defenseurdesdroits.fr/fr/saisir/delegues" url: "https://www.defenseurdesdroits.fr/fr/saisir/delegues"
title: "Contacter le délégué du Défenseur des droits dans votre région - nouvel onglet" title: "Contacter le délégué du Défenseur des droits dans votre région - nouvel onglet"
remedies_three_html: "Envoyer un courrier par la poste (gratuit, ne pas mettre de timbre) à l'adresse suivante : remedies_three_html: "Envoyer un courrier par la poste (gratuit, ne pas mettre de timbre) à ladresse suivante :
<p class=\"fr-mb-2w\">Défenseur des droits <p class=\"fr-mb-2w\">Défenseur des droits
<br >Libre réponse 71120 <br >Libre réponse 71120
<br>75342 Paris CEDEX 07</p>" <br>75342 Paris CEDEX 07</p>"
prefill_descriptions: prefill_descriptions:
edit: edit:
intro_html: "Vous souhaitez permettre à vos usager·ères la <strong>création d'un dossier prérempli</strong>, à partir de données dont vous disposez déjà, pour la démarche « %{libelle} »." intro_html: "Vous souhaitez permettre à vos usager·ères la <strong>création dun dossier prérempli</strong>, à partir de données dont vous disposez déjà, pour la démarche « %{libelle} »."
info_html: Pour cela, sélectionnez ci-dessous les champs que vous souhaitez préremplir.<br> Vous trouverez ensuite en bas de cette page un lien de préremplissage qu'il ne vous restera plus qu'à copier, à adapter en remplaçant les valeurs par défaut et à partager.<br> De la même façon, vous trouverez en bas de page un exemple de requête cURL à adapter si vous souhaitez préremplir les dossiers par API. info_html: Pour cela, sélectionnez ci-dessous les champs que vous souhaitez préremplir.<br> Vous trouverez ensuite en bas de cette page un lien de préremplissage quil ne vous restera plus quà copier, à adapter en remplaçant les valeurs par défaut et à partager.<br> De la même façon, vous trouverez en bas de page un exemple de requête cURL à adapter si vous souhaitez préremplir les dossiers par API.
champ_id: ID champ_id: ID
champ_type: Type champ_type: Type
entity_add: Ajouter entity_add: Ajouter
@ -259,9 +259,9 @@ fr:
rna_html: Un numéro RNA rna_html: Un numéro RNA
siret_html: Un numéro de SIRET siret_html: Un numéro de SIRET
repetition_html: Un tableau de dictionnaires avec les valeurs possibles pour chaque champ de la répétition. repetition_html: Un tableau de dictionnaires avec les valeurs possibles pour chaque champ de la répétition.
annuaire_education_html: Un code d'établissement scolaire, tel que défini par <a href="https://api.gouv.fr/les-api/api-annuaire-education" target="_blank" rel="noopener noreferrer">l'Annuaire de l'Éducation Nationale</a> annuaire_education_html: Un code détablissement scolaire, tel que défini par <a href="https://api.gouv.fr/les-api/api-annuaire-education" target="_blank" rel="noopener noreferrer">lAnnuaire de lÉducation Nationale</a>
dossier_link_html: Lidentifiant du dossier, sous forme de nombre entier dossier_link_html: Lidentifiant du dossier, sous forme de nombre entier
epci_html: Un tableau contenant le code de département et <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">celui de l'EPCI</a> epci_html: Un tableau contenant le code de département et <a href="https://geo.api.gouv.fr/epcis" target="_blank" rel="noopener noreferrer">celui de lEPCI</a>
examples: examples:
title: Exemple title: Exemple
prenom: "Jean" prenom: "Jean"
@ -393,15 +393,15 @@ fr:
a_suivre: Aucun instructeur nest affecté au suivi de ces dossiers. Soyez le premier ! a_suivre: Aucun instructeur nest affecté au suivi de ces dossiers. Soyez le premier !
suivis: Les dossiers qui sont dans cet onglet sont uniquement ceux que vous suivez. Vous pouvez échanger avec le demandeur jusquà pouvoir les accepter, les refuser ou les classer sans suite. suivis: Les dossiers qui sont dans cet onglet sont uniquement ceux que vous suivez. Vous pouvez échanger avec le demandeur jusquà pouvoir les accepter, les refuser ou les classer sans suite.
traites_html: "Les dossiers dans cet onglet sont terminés : ils ont été acceptés, refusés ou classés sans suite. Vous pouvez <a href=%{archives_path}>télécharger</a> les archives au format zip des dossiers terminés et leurs pièces jointes." traites_html: "Les dossiers dans cet onglet sont terminés : ils ont été acceptés, refusés ou classés sans suite. Vous pouvez <a href=%{archives_path}>télécharger</a> les archives au format zip des dossiers terminés et leurs pièces jointes."
tous: Tous les dossiers déposés sur cette démarche, qu'ils soient à suivre, suivis par vous ou suivis par d'autres instructeurs. tous: Tous les dossiers déposés sur cette démarche, quils soient à suivre, suivis par vous ou suivis par dautres instructeurs.
tous_with_routing: Tous les dossiers déposés sur cette démarche et attribués aux groupes d'instructeurs dont vous faites partie. tous_with_routing: Tous les dossiers déposés sur cette démarche et attribués aux groupes dinstructeurs dont vous faites partie.
supprimes: Tous les dossiers <strong>non archivés</strong>, <strong>terminés</strong> et <strong>supprimés par les instructeurs</strong> sur cette démarche supprimes: Tous les dossiers <strong>non archivés</strong>, <strong>terminés</strong> et <strong>supprimés par les instructeurs</strong> sur cette démarche
archives: "Les dossiers de cet onglet sont archivés : vous ne pouvez plus y répondre, et les demandeurs ne peuvent plus les modifier." archives: "Les dossiers de cet onglet sont archivés : vous ne pouvez plus y répondre, et les demandeurs ne peuvent plus les modifier."
expirant: Les dossiers nexpireront pas avant la période de conservation des données. expirant: Les dossiers nexpireront pas avant la période de conservation des données.
archived_dossier: "Le dossier sera conservé 1 mois supplémentaire" archived_dossier: "Le dossier sera conservé 1 mois supplémentaire"
delete_dossier: "Supprimer le dossier" delete_dossier: "Supprimer le dossier"
deleted_reason: deleted_reason:
user_request: supprimé par l'usager user_request: supprimé par lusager
expired: a expiré expired: a expiré
acts_on_behalf: "agit pour" acts_on_behalf: "agit pour"
deleted_by_administration: "Dossier supprimé par ladministration" deleted_by_administration: "Dossier supprimé par ladministration"
@ -412,7 +412,7 @@ fr:
select_all: Tout selectionner select_all: Tout selectionner
batch_operation: batch_operation:
enabled: "Ajouter le dossier %{dossier_id} à la sélection pour un traitement de masse" enabled: "Ajouter le dossier %{dossier_id} à la sélection pour un traitement de masse"
disabled: "Impossible d'ajouter le dossier %{dossier_id} à la selection car il est déjà dans un traitement de masse" disabled: "Impossible dajouter le dossier %{dossier_id} à la selection car il est déjà dans un traitement de masse"
show_deleted_dossiers: Historique des dossiers supprimés show_deleted_dossiers: Historique des dossiers supprimés
customize: Personnaliser le tableau customize: Personnaliser le tableau
passer_en_instruction: Passer en instruction passer_en_instruction: Passer en instruction
@ -477,7 +477,7 @@ fr:
delay_title: delay_title:
sva: "Votre dossier est soumis au cadre législatif « Silence Vaut Accord »" sva: "Votre dossier est soumis au cadre législatif « Silence Vaut Accord »"
svr: "Votre dossier est soumis au cadre législatif « Silence Vaut Rejet »" svr: "Votre dossier est soumis au cadre législatif « Silence Vaut Rejet »"
delay_text_sva_svr: "Vous aurez un retour de l'administration au plus tard le %{date}." delay_text_sva_svr: "Vous aurez un retour de ladministration au plus tard le %{date}."
status_completed: terminé status_completed: terminé
use_mailbox_for_questions_html: "<strong>Vous avez une question ?</strong> Utilisez la messagerie pour <a href=\"%{mailbox_url}\">contacter ladministration directement</a>." use_mailbox_for_questions_html: "<strong>Vous avez une question ?</strong> Utilisez la messagerie pour <a href=\"%{mailbox_url}\">contacter ladministration directement</a>."
acceptee_html: "Votre dossier a été <strong>accepté</strong>." acceptee_html: "Votre dossier a été <strong>accepté</strong>."
@ -519,12 +519,12 @@ fr:
other_html: Cette démarche est close. Vous ne pouvez pas déposer ce dossier, ni en déposer un nouveau pour cette démarche. %{link} other_html: Cette démarche est close. Vous ne pouvez pas déposer ce dossier, ni en déposer un nouveau pour cette démarche. %{link}
en_cours: en_cours:
internal_procedure_html: Cette démarche est close. Votre dossier est bien déposé et peut être instruit par ladministration. Au besoin, vous pouvez déposer un nouveau dossier sur la %{link} qui la remplace. internal_procedure_html: Cette démarche est close. Votre dossier est bien déposé et peut être instruit par ladministration. Au besoin, vous pouvez déposer un nouveau dossier sur la %{link} qui la remplace.
other_html: Cette démarche est close. Votre dossier est bien déposé et peut être instruit par l'administration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link} other_html: Cette démarche est close. Votre dossier est bien déposé et peut être instruit par ladministration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link}
termine: termine:
internal_procedure_html: Cette démarche est close. Votre dossier a bien été traité par l'administration. Au besoin, vous pouvez déposer un nouveau dossier sur la %{link} qui la remplace. internal_procedure_html: Cette démarche est close. Votre dossier a bien été traité par ladministration. Au besoin, vous pouvez déposer un nouveau dossier sur la %{link} qui la remplace.
other_html: Cette démarche est close. Votre dossier a bien été traité par l'administration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link} other_html: Cette démarche est close. Votre dossier a bien été traité par ladministration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link}
title_new_procedure: Nouvelle démarche disponible title_new_procedure: Nouvelle démarche disponible
title_closing_details: Plus d'informations sur la clôture de la démarche title_closing_details: Plus dinformations sur la clôture de la démarche
more_details: Plus dinformations more_details: Plus dinformations
procedure: démarche procedure: démarche
this_procedure: cette démarche this_procedure: cette démarche
@ -533,8 +533,8 @@ fr:
created_at: Créé le %{date} created_at: Créé le %{date}
updated_at: modifié le %{date} updated_at: modifié le %{date}
shared_with: Dossier partagé par %{owner} avec shared_with: Dossier partagé par %{owner} avec
deleted_by_user: Supprimé le %{date} par l'usager deleted_by_user: Supprimé le %{date} par lusager
deleted_by_automatic: Supprimé le %{date} automatiquement du à la date d'expiration deleted_by_automatic: Supprimé le %{date} automatiquement du à la date dexpiration
dossier_action: dossier_action:
edit_dossier: "Modifier le dossier" edit_dossier: "Modifier le dossier"
start_other_dossier: "Commencer un nouveau dossier" start_other_dossier: "Commencer un nouveau dossier"
@ -726,9 +726,9 @@ fr:
code_departement: code_departement:
not_in_departement_codes: "doit être un code de département valide" not_in_departement_codes: "doit être un code de département valide"
external_id: external_id:
not_in_departement_epci_codes: "doit être un code d'EPCI du département correspondant" not_in_departement_epci_codes: "doit être un code dEPCI du département correspondant"
value: value:
not_in_departement_epci_names: "doit être un nom d'EPCI du département correspondant" not_in_departement_epci_names: "doit être un nom dEPCI du département correspondant"
"champs/dossier_link_champ": "champs/dossier_link_champ":
attributes: attributes:
value: value:
@ -751,9 +751,9 @@ fr:
france_connect: france_connect:
connexion: "Erreur lors de la connexion à France Connect." connexion: "Erreur lors de la connexion à France Connect."
forbidden_html: "Seul-e-s les usagers peuvent se connecter via France Connect. En tant quinstructeur ou administrateur, nous vous invitons à <a href='%{reset_link}'>réininitialiser votre mot de passe</a>." forbidden_html: "Seul-e-s les usagers peuvent se connecter via France Connect. En tant quinstructeur ou administrateur, nous vous invitons à <a href='%{reset_link}'>réininitialiser votre mot de passe</a>."
evil_regexp: L'expression régulière que vous avez entrée est potentiellement dangereuse et pourrait entraîner des problèmes de performance evil_regexp: Lexpression régulière que vous avez entrée est potentiellement dangereuse et pourrait entraîner des problèmes de performance
mismatch_regexp: L'exemple doit correspondre à l'expression régulière fournie mismatch_regexp: Lexemple doit correspondre à lexpression régulière fournie
syntax_error_regexp: La syntaxe de l'expression régulière n'est pas valide syntax_error_regexp: La syntaxe de lexpression régulière nest pas valide
# procedure_not_draft: "Cette démarche nest maintenant plus en brouillon." # procedure_not_draft: "Cette démarche nest maintenant plus en brouillon."
cadastres_empty: cadastres_empty:
one: "Aucune parcelle cadastrale sur la zone sélectionnée" one: "Aucune parcelle cadastrale sur la zone sélectionnée"
@ -831,7 +831,7 @@ fr:
users: users:
dossiers: dossiers:
test_procedure: "Ce dossier est déposé sur une démarche en test. Toute modification de la démarche par ladministrateur (ajout dun champ, publication de la démarche...) entraînera sa suppression." test_procedure: "Ce dossier est déposé sur une démarche en test. Toute modification de la démarche par ladministrateur (ajout dun champ, publication de la démarche...) entraînera sa suppression."
no_access_html: "Vous navez pas accès à ce dossier.<br>Vérifiez que votre adresse email de connexion <b>%{email}</b> est bien celle utilisée pour remplir cette démarche.<br> Si ce n'est pas le cas, déconnectez-vous" no_access_html: "Vous navez pas accès à ce dossier.<br>Vérifiez que votre adresse email de connexion <b>%{email}</b> est bien celle utilisée pour remplir cette démarche.<br> Si ce nest pas le cas, déconnectez-vous"
no_longer_editable: "Votre dossier ne peut plus être modifié" no_longer_editable: "Votre dossier ne peut plus être modifié"
en_construction_submitted: "Les modifications ont déjà été déposées" en_construction_submitted: "Les modifications ont déjà été déposées"
fill_identity: fill_identity:
@ -934,19 +934,14 @@ fr:
particulier: particulier:
choose_email: choose_email:
intro_html: "Votre compte FranceConnect utilise <span class='fr-badge fr-badge--info fr-badge--no-icon fr-badge--lowercase'>%{email}</span> comme email de contact." intro_html: "Votre compte FranceConnect utilise <span class='fr-badge fr-badge--info fr-badge--no-icon fr-badge--lowercase'>%{email}</span> comme email de contact."
use_email_for_notifications: Souhaitez-vous l'utiliser pour recevoir les notifications concernant l'avancement de vos dossiers ? use_email_for_notifications: Souhaitez-vous lutiliser pour recevoir les notifications concernant lavancement de vos dossiers ?
confirm: Confirmer confirm: Valider
choose_email_contact: Choisissez votre email de contact pour finaliser votre connexion choose_email_contact: Choisissez votre email de contact pour finaliser votre connexion
alternative_email: Veuillez nous fournir l'email à utiliser pour vous contacter. alternative_email: Veuillez nous fournir ladresse électronique à utiliser pour vous contacter
keep_fc_email_html: "Oui, utiliser %{email} comme email de contact." keep_fc_email_html: "<span>Oui, utiliser <b>%{email}</b> comme email de contact</span>"
use_another_email: Non, utiliser une autre adresse. use_another_email: Non, utiliser une autre adresse
email_suggest: email_suggest:
wanna_say: 'Voulez-vous dire ?' wanna_say: 'Voulez-vous dire ?'
confirmation_sent:
confirmation_sent_by_email: Confirmez votre email
intro_html: "Un mail de confirmation a été envoyé à votre adresse <span class='fr-badge fr-badge--info fr-badge--no-icon fr-badge--lowercase'>%{email}</span>"
click_the_link_in_the_email: Vous devez impérativement cliquer sur le lien du mail pour activer votre adresse et recevoir les notifications sur l'avancement de vos dossiers.
continue: Continuer
merge: merge:
title: "Fusion des comptes FranceConnect et %{application_name}" title: "Fusion des comptes FranceConnect et %{application_name}"
subtitle_html: "Bonjour,<br /><br />Votre compte FranceConnect utilise <b class='bold'>%{email}</b> comme email de contact.<br />Or il existe un compte sur %{application_name} avec cet email." subtitle_html: "Bonjour,<br /><br />Votre compte FranceConnect utilise <b class='bold'>%{email}</b> comme email de contact.<br />Or il existe un compte sur %{application_name} avec cet email."
@ -970,16 +965,16 @@ fr:
flash: flash:
alert: alert:
groupe_gestionnaire_administrateur: groupe_gestionnaire_administrateur:
cannot_be_deleted: "L'administrateur « %{email} » ne peut pas être supprimé du groupe gestionnaire." cannot_be_deleted: "Ladministrateur « %{email} » ne peut pas être supprimé du groupe gestionnaire."
not_in_groupe_gestionnaire: "L'administrateur « %{email} » nest pas dans le groupe gestionnaire." not_in_groupe_gestionnaire: "Ladministrateur « %{email} » nest pas dans le groupe gestionnaire."
groupe_gestionnaire_gestionnaire: groupe_gestionnaire_gestionnaire:
destroy_at_least_one: "Suppression impossible : il doit y avoir au moins un gestionnaire dans le groupe racine" destroy_at_least_one: "Suppression impossible : il doit y avoir au moins un gestionnaire dans le groupe racine"
not_in_groupe_gestionnaire: "Le gestionnaire « %{email} » nest pas dans le groupe gestionnaire." not_in_groupe_gestionnaire: "Le gestionnaire « %{email} » nest pas dans le groupe gestionnaire."
notice: notice:
groupe_gestionnaire_administrateur: groupe_gestionnaire_administrateur:
create: "Les administrateurs ont bien été affectés au groupe gestionnaire" create: "Les administrateurs ont bien été affectés au groupe gestionnaire"
destroy: "L'administrateur « %{email} » a été supprimé." destroy: "Ladministrateur « %{email} » a été supprimé."
remove: "L'administrateur « %{email} » a été retiré du groupe gestionnaire." remove: "Ladministrateur « %{email} » a été retiré du groupe gestionnaire."
groupe_gestionnaire_gestionnaire: groupe_gestionnaire_gestionnaire:
create: "Les gestionnaires ont bien été affectés au groupe gestionnaire" create: "Les gestionnaires ont bien été affectés au groupe gestionnaire"
destroy: "Le gestionnaire « %{email} » a été retiré du groupe gestionnaire." destroy: "Le gestionnaire « %{email} » a été retiré du groupe gestionnaire."
@ -1011,7 +1006,7 @@ fr:
estimated_fill_duration: "Temps de remplissage estimé : %{estimated_minutes} min" estimated_fill_duration: "Temps de remplissage estimé : %{estimated_minutes} min"
estimated_fill_duration_title: Quelle est la durée de remplissage de la démarche ? estimated_fill_duration_title: Quelle est la durée de remplissage de la démarche ?
estimated_fill_duration_detail: "La durée de remplissage est estimée à %{estimated_minutes} min. Ce délai peut varier selon les options que vous choisirez." estimated_fill_duration_detail: "La durée de remplissage est estimée à %{estimated_minutes} min. Ce délai peut varier selon les options que vous choisirez."
usual_traitement_time_title: Quels sont les délais d'instruction pour cette démarche ? usual_traitement_time_title: Quels sont les délais dinstruction pour cette démarche ?
pieces_jointes : Quelles sont les pièces justificatives à fournir ? pieces_jointes : Quelles sont les pièces justificatives à fournir ?
pieces_jointes_conditionnal_list_title : Liste des pièces en fonction de votre situation pieces_jointes_conditionnal_list_title : Liste des pièces en fonction de votre situation
sva_svr_title: "Cette démarche applique le « %{rule} »" sva_svr_title: "Cette démarche applique le « %{rule} »"
@ -1019,5 +1014,5 @@ fr:
svr_text_html: "Le SVR, ou « <strong>Silence Vaut Rejet</strong> », est un principe législatif qui définit le comportement dune demande en cas dabsence de réponse de ladministration : la demande sera automatiquement refusée à lissue dun délai si votre dossier est complet." svr_text_html: "Le SVR, ou « <strong>Silence Vaut Rejet</strong> », est un principe législatif qui définit le comportement dune demande en cas dabsence de réponse de ladministration : la demande sera automatiquement refusée à lissue dun délai si votre dossier est complet."
sva_svr_prevision_date: sva_svr_prevision_date:
Ainsi, vous recevrez une réponse à votre demande dans les %{delay} après avoir déposé votre dossier complet. Ainsi, vous recevrez une réponse à votre demande dans les %{delay} après avoir déposé votre dossier complet.
Par exemple, si vous déposez votre dossier aujourd'hui, vous aurez une réponse au plus tard le %{date}. Par exemple, si vous déposez votre dossier aujourdhui, vous aurez une réponse au plus tard le %{date}.
Si votre dossier est incomplet, cette date pourrait être repoussée jusquà la soumission dun dossier complété. Si votre dossier est incomplet, cette date pourrait être repoussée jusquà la soumission dun dossier complété.

View file

@ -155,10 +155,9 @@ describe FranceConnect::ParticulierController, type: :controller do
user = User.last user = User.last
expect(user.email).to eq(email.downcase) expect(user.email).to eq(email.downcase)
expect(UserMailer).to have_received(:custom_confirmation_instructions).with(user, user.confirmation_token) expect(user.email_verified_at).not_to be_nil
expect(user.email_verified_at).to be_nil
expect(fci.reload.merge_token).to be_nil expect(fci.reload.merge_token).to be_nil
expect(response).to render_template(:confirmation_sent) expect(response).to redirect_to(root_path(user))
end end
end end

View file

@ -45,7 +45,7 @@ describe Gestionnaires::GroupeGestionnaireAdministrateursController, type: :cont
before { destroy(new_administrateur) } before { destroy(new_administrateur) }
it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(0) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(0) }
it { expect(flash.notice).to eq("L'administrateur « #{new_administrateur.email} » a été supprimé.") } it { expect(flash.notice).to eq("Ladministrateur « #{new_administrateur.email} » a été supprimé.") }
end end
context 'when administrateur has some procedure' do context 'when administrateur has some procedure' do
@ -57,7 +57,7 @@ describe Gestionnaires::GroupeGestionnaireAdministrateursController, type: :cont
end end
it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(2) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(2) }
it { expect(flash.alert).to eq("L'administrateur « #{administrateur_with_procedure.email} » ne peut pas être supprimé du groupe gestionnaire.") } it { expect(flash.alert).to eq("Ladministrateur « #{administrateur_with_procedure.email} » ne peut pas être supprimé du groupe gestionnaire.") }
end end
context 'when administrateur is not in the groupe_gestionnaire' do context 'when administrateur is not in the groupe_gestionnaire' do
@ -65,7 +65,7 @@ describe Gestionnaires::GroupeGestionnaireAdministrateursController, type: :cont
before { destroy(other_administrateur) } before { destroy(other_administrateur) }
it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(1) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(1) }
it { expect(flash.alert).to eq("L'administrateur « #{other_administrateur.email} » nest pas dans le groupe gestionnaire.") } it { expect(flash.alert).to eq("Ladministrateur « #{other_administrateur.email} » nest pas dans le groupe gestionnaire.") }
end end
end end
@ -90,7 +90,7 @@ describe Gestionnaires::GroupeGestionnaireAdministrateursController, type: :cont
before { remove(new_administrateur) } before { remove(new_administrateur) }
it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(0) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(0) }
it { expect(flash.notice).to eq("L'administrateur « #{new_administrateur.email} » a été retiré du groupe gestionnaire.") } it { expect(flash.notice).to eq("Ladministrateur « #{new_administrateur.email} » a été retiré du groupe gestionnaire.") }
end end
context 'when administrateur is not in the groupe_gestionnaire' do context 'when administrateur is not in the groupe_gestionnaire' do
@ -98,7 +98,7 @@ describe Gestionnaires::GroupeGestionnaireAdministrateursController, type: :cont
before { remove(other_administrateur) } before { remove(other_administrateur) }
it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(1) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(1) }
it { expect(flash.alert).to eq("L'administrateur « #{other_administrateur.email} » nest pas dans le groupe gestionnaire.") } it { expect(flash.alert).to eq("Ladministrateur « #{other_administrateur.email} » nest pas dans le groupe gestionnaire.") }
end end
end end
end end

View file

@ -7,7 +7,7 @@ describe 'France Connect Particulier Connexion' do
let(:birthdate) { '20150821' } let(:birthdate) { '20150821' }
let(:gender) { 'M' } let(:gender) { 'M' }
let(:birthplace) { '1234' } let(:birthplace) { '1234' }
let(:email) { 'plop@plop.com' } let(:fc_email) { 'plop@plop.com' }
let(:france_connect_particulier_id) { 'blabla' } let(:france_connect_particulier_id) { 'blabla' }
let(:user_info) do let(:user_info) do
@ -18,7 +18,7 @@ describe 'France Connect Particulier Connexion' do
birthdate: birthdate, birthdate: birthdate,
birthplace: birthplace, birthplace: birthplace,
gender: gender, gender: gender,
email_france_connect: email email_france_connect: fc_email
} }
end end
@ -40,32 +40,49 @@ describe 'France Connect Particulier Connexion' do
let(:france_connect_information) { build(:france_connect_information, user_info) } let(:france_connect_information) { build(:france_connect_information, user_info) }
context 'and no user has the same email' do context 'and no user has the same email' do
before { page.find('.fr-connect').click } before do
page.find('.fr-connect').click
scenario 'he is redirected to user dossiers page' do
expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion")
find("#use_france_connect_email_no").click
fill_in("email", with: "exemple@email.com")
page.find("input[type='submit'][name='commit'][value='Confirmer']").click
expect(page).to have_content("Confirmez votre email")
click_on 'Continuer'
expect(User.find_by(email: email)).not_to be nil
end end
scenario 'he can choose not to use FranceConnect email and input an alternative email' do scenario 'he is redirected to user dossiers page', js: true do
expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion") expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion")
find('label', text: "Oui, utiliser #{fc_email} comme email de contact").click
click_on 'Valider'
expect(User.find_by(email: fc_email).email_verified_at).to be_present
end
scenario 'he can choose not to use FranceConnect email and input an alternative email', js: true do
alternative_email = 'alternative@example.com'
expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion")
find('label', text: 'utiliser une autre adresse').click
expect(page).to have_selector("input[name='email']", visible: true, wait: 10) expect(page).to have_selector("input[name='email']", visible: true, wait: 10)
fill_in 'email', with: 'alternative@example.com' fill_in 'email', with: alternative_email
click_on 'Confirmer' click_on 'Valider'
expect(page).to have_content("Confirmez votre email") expect(page).to have_content('Nous venons de vous envoyer le mail de confirmation')
expect(User.find_by(email: alternative_email)).to be_nil
perform_enqueued_jobs
confirmation_email = open_email(alternative_email)
link = confirmation_email.body.match(/href="[^"]*(\/france_connect\/particulier\/merge_using_email_link.*?)"/)[1]
visit link
expect(page).to have_content('Les comptes FranceConnect et demarches-simplifiees.fr sont à présent fusionnés')
expect(page).to have_content(alternative_email)
expect(User.find_by(email: alternative_email).email_verified_at).to be_present
end end
end end
context 'and an user exists with the same email' do context 'and an user exists with the same email' do
let!(:user) { create(:user, email: email, password: SECURE_PASSWORD) } let!(:user) { create(:user, email: fc_email, password: SECURE_PASSWORD) }
before do before do
page.find('.fr-connect').click page.find('.fr-connect').click

View file

@ -182,12 +182,10 @@ describe 'Prefilling a dossier (with a GET request):', js: true do
page.find('.fr-connect').click page.find('.fr-connect').click
expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion") expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion")
expect(page).to have_selector("#use_france_connect_email_no", visible: false, wait: 10)
page.execute_script('document.getElementById("use_france_connect_email_no").click()') find('label', text: /Oui, utiliser .* comme email de contact/).click
fill_in("email", with: "exemple@email.com")
page.find("input[type='submit'][name='commit'][value='Confirmer']").click click_on 'Valider'
expect(page).to have_content("Confirmez votre email")
click_on 'Continuer'
expect(page).to have_content('Vous avez un dossier prérempli') expect(page).to have_content('Vous avez un dossier prérempli')
find('.fr-btn.fr-mb-2w', text: 'Poursuivre mon dossier prérempli', wait: 10).click find('.fr-btn.fr-mb-2w', text: 'Poursuivre mon dossier prérempli', wait: 10).click
end end

View file

@ -135,12 +135,10 @@ describe 'Prefilling a dossier (with a POST request):', js: true do
page.find('.fr-connect').click page.find('.fr-connect').click
expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion") expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion")
expect(page).to have_selector("#use_france_connect_email_yes", visible: false, wait: 10)
page.execute_script('document.getElementById("use_france_connect_email_yes").click()')
click_on 'Confirmer' find('label', text: /Oui, utiliser .* comme email de contact/).click
expect(page).to have_content("Confirmez votre email")
click_on 'Continuer' click_on 'Valider'
expect(page).to have_content('Vous avez un dossier prérempli') expect(page).to have_content('Vous avez un dossier prérempli')
find('.fr-btn.fr-mb-2w', text: 'Poursuivre mon dossier prérempli', wait: 10).click find('.fr-btn.fr-mb-2w', text: 'Poursuivre mon dossier prérempli', wait: 10).click
end end

View file

@ -56,7 +56,7 @@ describe 'shared/_procedure_description', type: :view do
it 'shows a usual traitement text' do it 'shows a usual traitement text' do
subject subject
expect(rendered).to have_text("Quels sont les délais d'instruction pour cette démarche ?") expect(rendered).to have_text("Quels sont les délais dinstruction pour cette démarche ?")
expect(rendered).to have_text("Dans le meilleur des cas, le délai dinstruction est : 1 jour.") expect(rendered).to have_text("Dans le meilleur des cas, le délai dinstruction est : 1 jour.")
end end
end end