Merge pull request #4981 from betagouv/fix-champ-policy-for-invite

Usager : corrige les champs Carte, SIRET et pièce justificative pour les invités
This commit is contained in:
Pierre de La Morinerie 2020-04-02 11:43:55 +02:00 committed by GitHub
commit 8f7a21317a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 12 deletions

View file

@ -5,16 +5,30 @@ class ChampPolicy < ApplicationPolicy
return scope.none
end
# The join must be the same for all elements of the WHERE clause.
#
# NB: here we want to do `.left_outer_joins(dossier: [:invites, { :groupe_instructeur: :instructeurs }]))`,
# but for some reasons ActiveRecord <= 5.2 generates bogus SQL. Hence the manual version of it below.
joined_scope = scope
.joins('LEFT OUTER JOIN dossiers ON dossiers.id = champs.dossier_id')
.joins('LEFT OUTER JOIN invites ON invites.dossier_id = dossiers.id')
.joins('LEFT OUTER JOIN groupe_instructeurs ON groupe_instructeurs.id = dossiers.groupe_instructeur_id')
.joins('LEFT OUTER JOIN assign_tos ON assign_tos.groupe_instructeur_id = groupe_instructeurs.id')
.joins('LEFT OUTER JOIN instructeurs ON instructeurs.id = assign_tos.instructeur_id')
# Users can access public champs on their own dossiers.
resolved_scope = scope
.left_outer_joins(dossier: { groupe_instructeur: [:instructeurs] })
resolved_scope = joined_scope
.where('dossiers.user_id': user.id, private: false)
# Invited users can access public champs on dossiers they are invited to
invite_clause = joined_scope
.where('invites.user_id': user.id, private: false)
resolved_scope = resolved_scope.or(invite_clause)
if instructeur.present?
# Additionnaly, instructeurs can access private champs
# on dossiers they are allowed to instruct.
instructeur_clause = scope
.left_outer_joins(dossier: { groupe_instructeur: [:instructeurs] })
instructeur_clause = joined_scope
.where('instructeurs.id': instructeur.id, private: true)
resolved_scope = resolved_scope.or(instructeur_clause)
end

View file

@ -1,6 +1,6 @@
describe ChampPolicy do
let(:champ) { create(:champ_text, private: private, dossier: dossier) }
let(:dossier) { create(:dossier, user: dossier_owner) }
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private) }
let(:dossier) { create(:dossier, procedure: procedure, user: dossier_owner) }
let(:dossier_owner) { create(:user) }
let(:signed_in_user) { create(:user) }
@ -8,24 +8,23 @@ describe ChampPolicy do
subject { Pundit.policy_scope(account, Champ) }
let(:champ) { dossier.champs.first }
let(:champ_private) { dossier.champs_private.first }
shared_examples_for 'they can access a public champ' do
let(:private) { false }
it { expect(subject.find_by(id: champ.id)).to eq(champ) }
end
shared_examples_for 'they cant access a public champ' do
let(:private) { false }
it { expect(subject.find_by(id: champ.id)).to eq(nil) }
end
shared_examples_for 'they can access a private champ' do
let(:private) { true }
it { expect(subject.find_by(id: champ.id)).to eq(champ) }
it { expect(subject.find_by(id: champ_private.id)).to eq(champ_private) }
end
shared_examples_for 'they cant access a private champ' do
let(:private) { true }
it { expect(subject.find_by(id: champ.id)).to eq(nil) }
it { expect(subject.find_by(id: champ_private.id)).to eq(nil) }
end
context 'when an user only has user rights' do
@ -36,6 +35,14 @@ describe ChampPolicy do
it_behaves_like 'they cant access a private champ'
end
context 'as a person invited on the dossier' do
let(:invite) { create(:invite, :with_user, dossier: dossier) }
let(:signed_in_user) { invite.user }
it_behaves_like 'they can access a public champ'
it_behaves_like 'they cant access a private champ'
end
context 'as another user' do
let(:signed_in_user) { create(:user) }