champ_policy: allow instructeurs to access private annotations
Fix #4388
This commit is contained in:
parent
a20b6b73a2
commit
c2e82e4145
2 changed files with 81 additions and 18 deletions
|
@ -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
|
||||||
|
|
|
@ -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 can’t 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 can’t 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 can’t access a private champ'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'as another user' do
|
||||||
|
let(:signed_in_user) { create(:user) }
|
||||||
|
|
||||||
|
it_behaves_like 'they can’t access a public champ'
|
||||||
|
it_behaves_like 'they can’t 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 can’t 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 can’t access a public champ'
|
||||||
|
it_behaves_like 'they can’t access a private champ'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue