champ_policy: allow instructeurs to access private annotations

Fix #4388
This commit is contained in:
Pierre de La Morinerie 2019-10-08 12:28:26 +00:00
parent a20b6b73a2
commit c2e82e4145
2 changed files with 81 additions and 18 deletions

View file

@ -1,13 +1,25 @@
class ChampPolicy < ApplicationPolicy class ChampPolicy < ApplicationPolicy
class Scope < ApplicationScope class Scope < ApplicationScope
def resolve def resolve
if user.present? if user.blank?
scope return scope.none
.joins(:dossier) end
.where({ dossiers: { user_id: user.id } })
else # Users can access public champs on their own dossiers.
scope.none resolved_scope = scope
end .left_outer_joins(dossier: { groupe_instructeur: [:instructeurs] })
.where('dossiers.user_id': user.id, private: false)
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] })
.where('instructeurs.id': instructeur.id, private: true)
resolved_scope = resolved_scope.or(instructeur_clause)
end
resolved_scope
end end
end end
end end

View file

@ -1,25 +1,76 @@
require 'spec_helper' require 'spec_helper'
describe ChampPolicy do describe ChampPolicy do
let(:user) { create(:user) } let(:champ) { create(:champ_text, private: private, dossier: dossier) }
let(:dossier) { create(:dossier, user: user) } let(:dossier) { create(:dossier, user: dossier_owner) }
let!(:champ) { create(:champ_text, dossier: dossier) } let(:dossier_owner) { create(:user) }
let(:account) { { user: user } } let(:signed_in_user) { create(:user) }
let(:account) { { user: signed_in_user } }
subject { Pundit.policy_scope(account, Champ) } subject { Pundit.policy_scope(account, Champ) }
context 'when the user has only user rights' do shared_examples_for 'they can access a public champ' do
context 'cannot access champs for other dossiers' do let(:private) { false }
let(:account) { { user: create(:user) } } 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) } it { expect(subject.find_by(id: champ.id)).to eq(nil) }
end end
context 'can access champs for its own dossiers' do shared_examples_for 'they can access a private champ' do
it { let(:private) { true }
expect(subject.find(champ.id)).to eq(champ) it { expect(subject.find_by(id: champ.id)).to eq(champ) }
} 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) }
end
context 'when an user only has user rights' do
context 'as the dossier owner' do
let(:signed_in_user) { dossier_owner }
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) }
it_behaves_like 'they cant access a public champ'
it_behaves_like 'they cant access a private champ'
end
end
context 'when the user also has instruction rights' do
let(:instructeur) { create(:instructeur, email: signed_in_user.email, password: signed_in_user.password) }
let(:account) { { user: signed_in_user, instructeur: instructeur } }
context 'as the dossier instructeur and owner' do
let(:signed_in_user) { dossier_owner }
before { instructeur.assign_to_procedure(dossier.procedure) }
it_behaves_like 'they can access a public champ'
it_behaves_like 'they can access a private champ'
end
context 'as the dossier instructeur (but not owner)' do
let(:signed_in_user) { create(:user) }
before { instructeur.assign_to_procedure(dossier.procedure) }
it_behaves_like 'they cant access a public champ'
it_behaves_like 'they can access a private champ'
end
context 'as an instructeur not assigned to the procedure' do
let(:signed_in_user) { create(:user) }
it_behaves_like 'they cant access a public champ'
it_behaves_like 'they cant access a private champ'
end end
end end
end end