Merge pull request #7197 from betagouv/7129-add_lien_dpo_to_procedure
feat(administrateur/procedure#create): allow admin to add a lien to the DPO, allow user to consult link to dpo. enhance spec on _procedure_footer.html
This commit is contained in:
commit
990c1ab6f6
14 changed files with 149 additions and 17 deletions
|
@ -254,7 +254,7 @@ module Administrateurs
|
||||||
end
|
end
|
||||||
|
|
||||||
def procedure_params
|
def procedure_params
|
||||||
editable_params = [:libelle, :description, :organisation, :direction, :lien_site_web, :cadre_juridique, :deliberation, :notice, :web_hook_url, :declarative_with_state, :logo, :auto_archive_on, :monavis_embed, :api_entreprise_token, :duree_conservation_dossiers_dans_ds, :zone_id]
|
editable_params = [:libelle, :description, :organisation, :direction, :lien_site_web, :cadre_juridique, :deliberation, :notice, :web_hook_url, :declarative_with_state, :logo, :auto_archive_on, :monavis_embed, :api_entreprise_token, :duree_conservation_dossiers_dans_ds, :zone_id, :lien_dpo]
|
||||||
permited_params = if @procedure&.locked?
|
permited_params = if @procedure&.locked?
|
||||||
params.require(:procedure).permit(*editable_params)
|
params.require(:procedure).permit(*editable_params)
|
||||||
else
|
else
|
||||||
|
|
|
@ -7,7 +7,9 @@ module ConservationDeDonneesHelper
|
||||||
|
|
||||||
def conservation_dans_ds(procedure)
|
def conservation_dans_ds(procedure)
|
||||||
if procedure.duree_conservation_dossiers_dans_ds.present?
|
if procedure.duree_conservation_dossiers_dans_ds.present?
|
||||||
"Dans #{APPLICATION_NAME} : #{procedure.duree_conservation_dossiers_dans_ds} mois"
|
I18n.t('users.procedure_footer.legals.data_retention',
|
||||||
|
application_name: APPLICATION_NAME,
|
||||||
|
duree_conservation_dossiers_dans_ds: procedure.duree_conservation_dossiers_dans_ds)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -74,4 +74,12 @@ module ProcedureHelper
|
||||||
.includes(:groupe_instructeur)
|
.includes(:groupe_instructeur)
|
||||||
.exists?(groupe_instructeur: current_instructeur.groupe_instructeurs)
|
.exists?(groupe_instructeur: current_instructeur.groupe_instructeurs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def url_or_email_to_lien_dpo(procedure)
|
||||||
|
URI::MailTo.build([procedure.lien_dpo, "subject="]).to_s
|
||||||
|
rescue URI::InvalidComponentError
|
||||||
|
uri = URI.parse(procedure.lien_dpo)
|
||||||
|
return "//#{uri}" if uri.scheme.nil?
|
||||||
|
uri.to_s
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
# juridique_required :boolean default(TRUE)
|
# juridique_required :boolean default(TRUE)
|
||||||
# libelle :string
|
# libelle :string
|
||||||
# lien_demarche :string
|
# lien_demarche :string
|
||||||
|
# lien_dpo :string
|
||||||
# lien_notice :string
|
# lien_notice :string
|
||||||
# lien_site_web :string
|
# lien_site_web :string
|
||||||
# monavis_embed :text
|
# monavis_embed :text
|
||||||
|
@ -266,6 +267,7 @@ class Procedure < ApplicationRecord
|
||||||
validate :check_juridique
|
validate :check_juridique
|
||||||
validates :path, presence: true, format: { with: /\A[a-z0-9_\-]{3,200}\z/ }, uniqueness: { scope: [:path, :closed_at, :hidden_at, :unpublished_at], case_sensitive: false }
|
validates :path, presence: true, format: { with: /\A[a-z0-9_\-]{3,200}\z/ }, uniqueness: { scope: [:path, :closed_at, :hidden_at, :unpublished_at], case_sensitive: false }
|
||||||
validates :duree_conservation_dossiers_dans_ds, allow_nil: false, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: MAX_DUREE_CONSERVATION }
|
validates :duree_conservation_dossiers_dans_ds, allow_nil: false, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: MAX_DUREE_CONSERVATION }
|
||||||
|
validates :lien_dpo, email_or_link: true, allow_nil: true
|
||||||
validates_with MonAvisEmbedValidator
|
validates_with MonAvisEmbedValidator
|
||||||
|
|
||||||
FILE_MAX_SIZE = 20.megabytes
|
FILE_MAX_SIZE = 20.megabytes
|
||||||
|
|
7
app/validators/email_or_link_validator.rb
Normal file
7
app/validators/email_or_link_validator.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class EmailOrLinkValidator < ActiveModel::EachValidator
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
URI.parse(value)
|
||||||
|
rescue URI::InvalidURIError
|
||||||
|
record.errors.add(attribute, :invalid_uri_or_email)
|
||||||
|
end
|
||||||
|
end
|
|
@ -57,6 +57,13 @@
|
||||||
= f.label :deliberation, 'Importer le texte'
|
= f.label :deliberation, 'Importer le texte'
|
||||||
= text_upload_and_render f, @procedure.deliberation
|
= text_upload_and_render f, @procedure.deliberation
|
||||||
|
|
||||||
|
%h3.header-subsection
|
||||||
|
RGPD
|
||||||
|
%p.notice
|
||||||
|
Pour certaines démarches, veuillez indiquer soit un mail le mail de contact de votre délégué à la protection des données, soit un lien web pointant vers les informations
|
||||||
|
|
||||||
|
= f.label :lien_dpo, 'Lien ou email pour contacter le Délégué à la Protection des Données (DPO)'
|
||||||
|
= f.text_field :lien_dpo, class: 'form-control'
|
||||||
%h3.header-subsection Notice explicative de la démarche
|
%h3.header-subsection Notice explicative de la démarche
|
||||||
|
|
||||||
%p.notice
|
%p.notice
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
- if service.present?
|
- if service.present?
|
||||||
.footer-row.footer-columns
|
.footer-row.footer-columns
|
||||||
.footer-column
|
.footer-column
|
||||||
%p.footer-header Cette démarche est gérée par :
|
%p.footer-header= I18n.t('users.procedure_footer.managed_by.header')
|
||||||
%ul
|
%ul
|
||||||
%li
|
%li
|
||||||
= service.nom
|
= service.nom
|
||||||
|
@ -14,46 +14,49 @@
|
||||||
= string_to_html(service.adresse, wrapper_tag = 'span')
|
= string_to_html(service.adresse, wrapper_tag = 'span')
|
||||||
|
|
||||||
.footer-column
|
.footer-column
|
||||||
%p.footer-header Poser une question sur votre dossier :
|
%p.footer-header= I18n.t('users.procedure_footer.contact.header')
|
||||||
%ul
|
%ul
|
||||||
%li
|
%li
|
||||||
- if dossier.present? && dossier.messagerie_available?
|
- if dossier.present? && dossier.messagerie_available?
|
||||||
Directement
|
= I18n.t('users.procedure_footer.contact.in_app_mail.prefix')
|
||||||
= link_to "par la messagerie", messagerie_dossier_path(dossier)
|
= link_to I18n.t('users.procedure_footer.contact.in_app_mail.link'), messagerie_dossier_path(dossier)
|
||||||
- else
|
- else
|
||||||
Par email :
|
= I18n.t('users.procedure_footer.contact.email.prefix')
|
||||||
= link_to service.email, "mailto:#{service.email}"
|
= link_to service.email, "mailto:#{service.email}"
|
||||||
|
|
||||||
- if service.telephone.present?
|
- if service.telephone.present?
|
||||||
%li
|
%li
|
||||||
Par téléphone :
|
= I18n.t('users.procedure_footer.contact.phone.prefix')
|
||||||
= link_to service.telephone, service.telephone_url
|
= link_to service.telephone, service.telephone_url
|
||||||
|
|
||||||
%li
|
%li
|
||||||
- horaires = "Horaires : #{formatted_horaires(service.horaires)}"
|
- horaires = "#{I18n.t('users.procedure_footer.contact.schedule.prefix')}#{formatted_horaires(service.horaires)}"
|
||||||
= simple_format(horaires, {}, wrapper_tag: 'span')
|
= simple_format(horaires, {}, wrapper_tag: 'span')
|
||||||
|
|
||||||
%li
|
%li
|
||||||
Statistiques :
|
= I18n.t('users.procedure_footer.contact.stats.prefix')
|
||||||
= link_to "voir les statistiques de la démarche", statistiques_path(procedure.path)
|
= link_to I18n.t('users.procedure_footer.contact.stats.cta'), statistiques_path(procedure.path)
|
||||||
|
|
||||||
|
|
||||||
- politiques = politiques_conservation_de_donnees(procedure)
|
- politiques = politiques_conservation_de_donnees(procedure)
|
||||||
- if politiques.present?
|
- if politiques.present?
|
||||||
.footer-column
|
.footer-column
|
||||||
%p.footer-header Conservation des données :
|
%p.footer-header= I18n.t('users.procedure_footer.legals.header')
|
||||||
%ul
|
%ul
|
||||||
- politiques.each do |politique|
|
- politiques.each do |politique|
|
||||||
%li= politique
|
%li= politique
|
||||||
%p.mt-2.footer-header Cadre juridique :
|
|
||||||
%ul
|
|
||||||
- if procedure.deliberation.attached?
|
- if procedure.deliberation.attached?
|
||||||
%li
|
%li
|
||||||
= link_to url_for(procedure.deliberation), target: '_blank', rel: 'noopener' do
|
= link_to url_for(procedure.deliberation), target: '_blank', rel: 'noopener' do
|
||||||
= "Texte cadrant la demande d'information"
|
= I18n.t("users.procedure_footer.legals.terms")
|
||||||
- else
|
- else
|
||||||
%li
|
%li
|
||||||
= link_to "Texte juridique la demande d'information", procedure.cadre_juridique, target: '_blank', rel: 'noopener'
|
= link_to I18n.t("users.procedure_footer.legals.terms"), procedure.cadre_juridique, target: '_blank', rel: 'noopener'
|
||||||
|
|
||||||
|
- if procedure.lien_dpo.present?
|
||||||
|
%li
|
||||||
|
= link_to url_or_email_to_lien_dpo(procedure), target: '_blank', rel: 'noopener' do
|
||||||
|
= I18n.t("users.procedure_footer.legals.dpo")
|
||||||
|
|
||||||
= render partial: 'users/general_footer_row', locals: { dossier: dossier }
|
= render partial: 'users/general_footer_row', locals: { dossier: dossier }
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ fr:
|
||||||
declarative_with_state/en_instruction: En instruction
|
declarative_with_state/en_instruction: En instruction
|
||||||
declarative_with_state/accepte: Accepté
|
declarative_with_state/accepte: Accepté
|
||||||
api_particulier_token: Jeton API Particulier
|
api_particulier_token: Jeton API Particulier
|
||||||
|
lien_dpo: Contact du DPO
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
procedure:
|
procedure:
|
||||||
|
@ -27,3 +28,5 @@ fr:
|
||||||
format: 'Le champ %{message}'
|
format: 'Le champ %{message}'
|
||||||
draft_types_de_champ_private:
|
draft_types_de_champ_private:
|
||||||
format: 'L’annotation privée %{message}'
|
format: 'L’annotation privée %{message}'
|
||||||
|
lien_dpo:
|
||||||
|
invalid_uri_or_email: "Veuillez saisir un mail ou un lien"
|
||||||
|
|
24
config/locales/views/users/procedure_footer/en.yml
Normal file
24
config/locales/views/users/procedure_footer/en.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
en:
|
||||||
|
users:
|
||||||
|
procedure_footer:
|
||||||
|
managed_by:
|
||||||
|
header: 'This procedure is managed by :'
|
||||||
|
contact:
|
||||||
|
header: 'Ask a question about your file :'
|
||||||
|
in_app_mail:
|
||||||
|
prefix: 'Directly :'
|
||||||
|
link: "via the chat"
|
||||||
|
email:
|
||||||
|
prefix: 'By mail :'
|
||||||
|
phone:
|
||||||
|
prefix: 'By phone :'
|
||||||
|
schedule:
|
||||||
|
prefix: 'Hours : '
|
||||||
|
stats:
|
||||||
|
prefix: 'Stats :'
|
||||||
|
cta: "see the procedure's stats"
|
||||||
|
legals:
|
||||||
|
header: "Legals :"
|
||||||
|
data_retention: "Within %{application_name} : %{duree_conservation_dossiers_dans_ds} months"
|
||||||
|
terms: "Laws regarding this data collection"
|
||||||
|
dpo: "Contact the Data Protection Officer"
|
24
config/locales/views/users/procedure_footer/fr.yml
Normal file
24
config/locales/views/users/procedure_footer/fr.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
fr:
|
||||||
|
users:
|
||||||
|
procedure_footer:
|
||||||
|
managed_by:
|
||||||
|
header: 'Cette démarche est gérée par :'
|
||||||
|
contact:
|
||||||
|
header: 'Poser une question sur votre dossier :'
|
||||||
|
in_app_mail:
|
||||||
|
prefix: 'Directement :'
|
||||||
|
link: "par la messagerie"
|
||||||
|
email:
|
||||||
|
prefix: 'Par email :'
|
||||||
|
phone:
|
||||||
|
prefix: 'Par téléphone :'
|
||||||
|
schedule:
|
||||||
|
prefix: 'Horaires : '
|
||||||
|
stats:
|
||||||
|
prefix: 'Statistiques :'
|
||||||
|
cta: "voir les statistiques de la démarche"
|
||||||
|
legals:
|
||||||
|
header: "Cadre juridique :"
|
||||||
|
data_retention: "Dans %{application_name} : %{duree_conservation_dossiers_dans_ds} mois"
|
||||||
|
terms: "Texte cadrant la demande d'information"
|
||||||
|
dpo: "Contacter le Délégué à la Protection des Données"
|
5
db/migrate/20220425140107_add_lien_dpo_to_procedure.rb
Normal file
5
db/migrate/20220425140107_add_lien_dpo_to_procedure.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddLienDpoToProcedure < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
add_column :procedures, :lien_dpo, :string
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2022_04_07_081538) do
|
ActiveRecord::Schema.define(version: 2022_04_25_140107) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -645,6 +645,7 @@ ActiveRecord::Schema.define(version: 2022_04_07_081538) do
|
||||||
t.boolean "juridique_required", default: true
|
t.boolean "juridique_required", default: true
|
||||||
t.string "libelle"
|
t.string "libelle"
|
||||||
t.string "lien_demarche"
|
t.string "lien_demarche"
|
||||||
|
t.string "lien_dpo"
|
||||||
t.string "lien_notice"
|
t.string "lien_notice"
|
||||||
t.string "lien_site_web"
|
t.string "lien_site_web"
|
||||||
t.text "monavis_embed"
|
t.text "monavis_embed"
|
||||||
|
|
|
@ -1185,6 +1185,13 @@ describe Procedure do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'lien_dpo' do
|
||||||
|
it { expect(build(:procedure).valid?).to be(true) }
|
||||||
|
it { expect(build(:procedure, lien_dpo: 'dpo@ministere.amere').valid?).to be(true) }
|
||||||
|
it { expect(build(:procedure, lien_dpo: 'https://legal.fr/contact_dpo').valid?).to be(true) }
|
||||||
|
it { expect(build(:procedure, lien_dpo: 'askjdlad l akdj asd ').valid?).to be(false) }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def create_dossier_with_pj_of_size(size, procedure)
|
def create_dossier_with_pj_of_size(size, procedure)
|
||||||
|
|
|
@ -27,4 +27,43 @@ describe 'users/procedure_footer.html.haml', type: :view do
|
||||||
it { is_expected.to have_link("Accessibilité") }
|
it { is_expected.to have_link("Accessibilité") }
|
||||||
it { is_expected.not_to have_text('téléphone') }
|
it { is_expected.not_to have_text('téléphone') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#cadre_juridique' do
|
||||||
|
context 'when an external link is provided' do
|
||||||
|
before { dossier.procedure.update(cadre_juridique: "http://google.fr") }
|
||||||
|
it { is_expected.to have_link("Texte cadrant la demande d'information", href: 'http://google.fr') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there is deliberation attached' do
|
||||||
|
before { dossier.procedure.update(cadre_juridique: nil, deliberation: fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf')) }
|
||||||
|
it { is_expected.to have_link("Texte cadrant la demande d'information") }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#lien_dpo' do
|
||||||
|
context "when there is not lien_dpo" do
|
||||||
|
before { dossier.procedure.update(lien_dpo: nil) }
|
||||||
|
it { is_expected.not_to have_text('Contacter le Délégué à la Protection des Données') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there is a lien_dpo with an email" do
|
||||||
|
before { dossier.procedure.update(lien_dpo: 'dpo@beta.gouv.fr') }
|
||||||
|
it { is_expected.to have_selector('a[href="mailto:dpo@beta.gouv.fr?subject="]') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there is a lien_dpo with a schemaless link" do
|
||||||
|
before { dossier.procedure.update(lien_dpo: 'beta.gouv.fr') }
|
||||||
|
it { is_expected.to have_link('Contacter le Délégué à la Protection des Données', href: '//beta.gouv.fr') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there is a lien_dpo with a link with http:// schema" do
|
||||||
|
before { dossier.procedure.update(lien_dpo: 'http://beta.gouv.fr') }
|
||||||
|
it { is_expected.to have_link('Contacter le Délégué à la Protection des Données', href: 'http://beta.gouv.fr') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there is a lien_dpo with a link with https:// schema" do
|
||||||
|
before { dossier.procedure.update(lien_dpo: 'https://beta.gouv.fr') }
|
||||||
|
it { is_expected.to have_link('Contacter le Délégué à la Protection des Données', href: 'https://beta.gouv.fr') }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue