-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ajout du champ notification_email
pour les usagers, modifiable uniquement via l'api (par rdv-insertion)
#5003
base: production
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ def index | |
end | ||
|
||
def show | ||
render_record @user, agent_context: pundit_user | ||
render_record @user, agent_context: pundit_user, include_notification_email: rdvinsertion_request? | ||
end | ||
|
||
def create | ||
|
@@ -19,13 +19,13 @@ def create | |
authorize(user, policy_class: Agent::UserPolicy) | ||
user.skip_confirmation_notification! | ||
user.save! | ||
render_record user | ||
render_record user, include_notification_email: rdvinsertion_request? | ||
end | ||
|
||
def update | ||
@user.skip_reconfirmation! | ||
@user.update!(user_params) | ||
render_record @user | ||
render_record @user, include_notification_email: rdvinsertion_request? | ||
end | ||
|
||
def rdv_invitation_token | ||
|
@@ -47,14 +47,18 @@ def set_user | |
end | ||
|
||
def user_params | ||
attrs = %i[ | ||
base_attrs = %i[ | ||
first_name birth_name last_name email address phone_number | ||
birth_date responsible_id caisse_affiliation affiliation_number | ||
family_situation number_of_children notify_by_sms notify_by_email | ||
] | ||
|
||
attrs -= User::FranceconnectFrozenFieldsConcern::FROZEN_FIELDS if @user&.logged_once_with_franceconnect? | ||
# Seul rdv-insertion peut enregistrer l'email de notification des usagers | ||
# Celui ci permet de notifier plusieurs usagers avec le même email | ||
base_attrs << :notification_email if rdvinsertion_request? | ||
Comment on lines
-56
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Je trouve ça étonnant qu'on ait un champ uniquement dispo à RDV-I dans notre API publique. Quel est le risque de rendre ce champ utilisable par n'importe qui ? |
||
|
||
params.permit(attrs, organisation_ids: [], referent_agent_ids: []) | ||
base_attrs -= User::FranceconnectFrozenFieldsConcern::FROZEN_FIELDS if @user&.logged_once_with_franceconnect? | ||
|
||
params.permit(base_attrs, organisation_ids: [], referent_agent_ids: []) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ def self.search_options | |
|
||
# Attributes | ||
ONGOING_MARGIN = 1.hour.freeze | ||
auto_strip_attributes :email, :first_name, :last_name, :birth_name | ||
auto_strip_attributes :email, :notification_email, :first_name, :last_name, :birth_name | ||
|
||
enum :caisse_affiliation, { aucune: 0, caf: 1, msa: 2 } | ||
enum :family_situation, { single: 0, in_a_relationship: 1, divorced: 2 } | ||
|
@@ -72,6 +72,7 @@ def self.search_options | |
|
||
# Hooks | ||
before_save :set_email_to_null_if_blank | ||
before_save :clear_notification_email_if_email_present | ||
|
||
# Scopes | ||
default_scope { where(deleted_at: nil) } | ||
|
@@ -90,6 +91,11 @@ def email=(value) | |
super(value&.gsub(".@", "@")&.gsub("..", ".")) | ||
end | ||
|
||
def notification_email=(value) | ||
# On applique les mêmes corrections pour notification_email | ||
super(value&.gsub(".@", "@")&.gsub("..", ".")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Je pense qu'on peut factoriser dans une méthode de classe du genre |
||
end | ||
|
||
def add_organisation(organisation) | ||
self_and_relatives_and_responsible.each do |u| | ||
u.organisations << organisation if u.organisation_ids.exclude?(organisation.id) | ||
|
@@ -275,6 +281,10 @@ def set_email_to_null_if_blank | |
self.email = nil if email.blank? | ||
end | ||
|
||
def clear_notification_email_if_email_present | ||
self.notification_email = nil if email.present? | ||
end | ||
|
||
def birth_date_validity | ||
return unless birth_date.present? && (birth_date > Time.zone.today || birth_date < 130.years.ago) | ||
|
||
|
@@ -297,7 +307,8 @@ def do_soft_delete(organisation) | |
first_name: "Usager supprimé", | ||
last_name: "Usager supprimé", | ||
deleted_at: Time.zone.now, | ||
email: deleted_email | ||
email: deleted_email, | ||
notification_email: nil | ||
) | ||
reload # anonymizer operates outside the realm of rails knowledge | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class AddNotificationEmailToUser < ActiveRecord::Migration[7.1] | ||
disable_ddl_transaction! | ||
|
||
def change | ||
add_column :users, :notification_email, :string | ||
add_index :users, :notification_email, algorithm: :concurrently | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Un index partiel ( |
||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
RSpec.describe "rdv-insertion API: users" do | ||
let(:agent) { create(:agent, basic_role_in_organisations: [organisation_rdv_insertion]) } | ||
let(:user) { create(:user, organisations: [organisation_rdv_insertion, other_organisation_rdv_insertion, organisation_rdv_solidarites]) } | ||
let(:user) { create(:user, :with_no_email, notification_email: "[email protected]", organisations: [organisation_rdv_insertion, other_organisation_rdv_insertion, organisation_rdv_solidarites]) } | ||
|
||
let(:shared_secret) { "S3cr3T" } | ||
let(:auth_headers) { api_auth_headers_with_shared_secret(agent, shared_secret) } | ||
|
@@ -19,5 +19,6 @@ | |
response_user_profiles = response.parsed_body.dig("user", "user_profiles") | ||
response_organisation_ids = response_user_profiles.map { |user_profile| user_profile.dig("organisation", "id") } | ||
expect(response_organisation_ids).to contain_exactly(organisation_rdv_insertion.id, other_organisation_rdv_insertion.id) | ||
expect(parsed_response_body["user"]["notification_email"]).to eq("[email protected]") | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,6 +77,7 @@ | |
parameter name: "birth_name", in: :query, type: :string, description: "Nom de naissance", example: "Fripouille", required: false | ||
parameter name: "birth_date", in: :query, type: :string, description: "Date de naissance", example: "1976-10-01", required: false | ||
parameter name: "email", in: :query, type: :string, description: "Email", example: "[email protected]", required: false | ||
parameter name: "notification_email", in: :query, type: :string, description: "Email de notification", required: false, document: false | ||
parameter name: "phone_number", in: :query, type: :string, description: "Numéro de téléphone", example: "33600008012", required: false | ||
parameter name: "address", in: :query, type: :string, description: "Adresse", example: "10 rue du Havre, Paris, 75016", required: false | ||
parameter name: "caisse_affiliation", in: :query, type: :string, description: "Caisse d'affiliation", example: "caf", required: false | ||
|
@@ -148,6 +149,22 @@ | |
it { expect(user.reload.responsible).to eq(user_responsible) } | ||
end | ||
|
||
response 200, "cannot update notification_email field without shared secret auth", document: false do | ||
before do | ||
user.update(email: nil) # notification_email can't be set if devise email is set | ||
end | ||
|
||
let(:notification_email) { "[email protected]" } | ||
let(:first_name) { "Alain" } | ||
let(:last_name) { "Verse" } | ||
|
||
run_test! | ||
|
||
it { expect(user.reload.first_name).to eq(first_name) } | ||
it { expect(user.reload.last_name).to eq(last_name) } | ||
it { expect(user.reload.notification_email).to be_nil } | ||
end | ||
|
||
response 200, "updates a user with a minimal set of params", document: false do | ||
let(:first_name) { "Alain" } | ||
let(:last_name) { "Verse" } | ||
|
@@ -199,6 +216,45 @@ | |
let(:email) { existing_user.email } | ||
end | ||
end | ||
|
||
patch "Mettre à jour un·e usager·ère via l'authentification shared secret", params: { document: false } do | ||
with_shared_secret_authentication | ||
|
||
tags "User" | ||
produces "application/json" | ||
operationId "updateUser" | ||
description "Met à jour un·e usager·ère" | ||
|
||
parameter name: :user_id, in: :path, type: :integer, description: "ID de l'usager·ère", example: 123 | ||
parameter name: "first_name", in: :query, type: :string, description: "Prénom", example: "Johnny", required: false | ||
parameter name: "last_name", in: :query, type: :string, description: "Nom", example: "Silverhand", required: false | ||
parameter name: "notification_email", in: :query, type: :string, description: "Email de notification", required: false, document: false | ||
|
||
let(:user) { create(:user, :with_no_email, first_name: "Jean", last_name: "JACQUES", organisations: [organisation]) } | ||
let(:user_id) { user.id } | ||
|
||
before do | ||
allow(Agent).to receive(:find_by).and_return(agent) | ||
allow(ENV).to receive(:fetch).with("SHARED_SECRET_FOR_AGENTS_AUTH").and_return(shared_secret) | ||
allow(ActiveSupport::SecurityUtils).to receive(:secure_compare).and_return(true) | ||
end | ||
|
||
let!(:shared_secret) { "S3cr3T" } | ||
let!(:auth_headers) { api_auth_headers_with_shared_secret(agent, shared_secret) } | ||
let!(:uid) { auth_headers["uid"].to_s } | ||
let!(:"X-Agent-Auth-Signature") { auth_headers["X-Agent-Auth-Signature"].to_s } | ||
|
||
response 200, "updates notification_email when authenticated through rdvinsertion", document: false do | ||
let(:notification_email) { "[email protected]" } | ||
let(:first_name) { "Alain" } | ||
let(:last_name) { "Verse" } | ||
|
||
run_test! | ||
|
||
it { expect(parsed_response_body["user"]["notification_email"]).to eq(notification_email) } | ||
it { expect(user.reload.notification_email).to eq(notification_email) } | ||
end | ||
end | ||
end | ||
|
||
path "/api/v1/users/{user_id}/rdv_invitation_token" do | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A voir si on ne souhaite pas conditionner de cette façon, on pourrait toujours afficher le champ si il est rempli par exemple.