implemented team-dependent exercise policy

This commit is contained in:
Hauke Klement
2015-01-29 17:13:22 +01:00
parent a6d3c7c539
commit cbde9529aa
2 changed files with 28 additions and 9 deletions

View File

@ -4,20 +4,27 @@ class ExercisePolicy < AdminOrAuthorPolicy
end end
private :author? private :author?
[:clone?, :statistics?].each do |action| [:clone?, :destroy?, :edit?, :show?, :statistics?, :update?].each do |action|
define_method(action) { admin? || author? } define_method(action) { admin? || author? || team_member? }
end end
[:implement?, :submit?].each do |action| [:implement?, :submit?].each do |action|
define_method(action) { everyone } define_method(action) { everyone }
end end
def team_member?
@record.team.try(:members, []).include?(@user)
end
private :team_member?
class Scope < Scope class Scope < Scope
def resolve def resolve
if @user.admin? if @user.admin?
@scope.all @scope.all
elsif @user.internal?
@scope.where("user_id = #{@user.id} OR public = TRUE OR (team_id IS NOT NULL AND team_id IN (SELECT t.id FROM teams t JOIN internal_users_teams iut ON t.id = iut.team_id WHERE iut.internal_user_id = #{@user.id}))")
else else
@scope.where("user_id = #{@user.id} OR public = TRUE") @scope.none
end end
end end
end end

View File

@ -3,7 +3,7 @@ require 'rails_helper'
describe ExercisePolicy do describe ExercisePolicy do
subject { ExercisePolicy } subject { ExercisePolicy }
let(:exercise) { FactoryGirl.build(:fibonacci) } let(:exercise) { FactoryGirl.build(:fibonacci, team: FactoryGirl.create(:team)) }
[:create?, :index?, :new?].each do |action| [:create?, :index?, :new?].each do |action|
permissions(action) do permissions(action) do
@ -21,7 +21,7 @@ describe ExercisePolicy do
end end
end end
[:destroy?, :edit?, :show?, :update?].each do |action| [:clone?, :destroy?, :edit?, :show?, :statistics?, :update?].each do |action|
permissions(action) do permissions(action) do
it 'grants access to admins' do it 'grants access to admins' do
expect(subject).to permit(FactoryGirl.build(:admin), exercise) expect(subject).to permit(FactoryGirl.build(:admin), exercise)
@ -31,6 +31,10 @@ describe ExercisePolicy do
expect(subject).to permit(exercise.author, exercise) expect(subject).to permit(exercise.author, exercise)
end end
it 'grants access to team members' do
expect(subject).to permit(exercise.team.members.first, exercise)
end
it 'does not grant access to all other users' do it 'does not grant access to all other users' do
[:external_user, :teacher].each do |factory_name| [:external_user, :teacher].each do |factory_name|
expect(subject).not_to permit(FactoryGirl.build(factory_name), exercise) expect(subject).not_to permit(FactoryGirl.build(factory_name), exercise)
@ -54,11 +58,15 @@ describe ExercisePolicy do
let(:admin) { FactoryGirl.create(:admin) } let(:admin) { FactoryGirl.create(:admin) }
let(:external_user) { FactoryGirl.create(:external_user) } let(:external_user) { FactoryGirl.create(:external_user) }
let(:teacher) { FactoryGirl.create(:teacher) } let(:teacher) { FactoryGirl.create(:teacher) }
let(:team) { FactoryGirl.create(:team) }
before(:each) do before(:each) do
[admin, teacher].each do |user| [admin, teacher].each do |user|
[true, false].each do |public| [true, false].each do |public|
FactoryGirl.create(:fibonacci, public: public, user_id: user.id, user_type: InternalUser.class.name) team.members << teacher
[team, nil].each do |team|
FactoryGirl.create(:fibonacci, public: public, team: team, user_id: user.id, user_type: InternalUser.class.name)
end
end end
end end
end end
@ -74,8 +82,8 @@ describe ExercisePolicy do
context 'for external users' do context 'for external users' do
let(:scope) { Pundit.policy_scope!(external_user, Exercise) } let(:scope) { Pundit.policy_scope!(external_user, Exercise) }
it 'returns only public exercises' do it 'returns nothing' do
expect(scope.map(&:id)).to include(*Exercise.where(public: true).map(&:id)) expect(scope.count).to be 0
end end
end end
@ -90,8 +98,12 @@ describe ExercisePolicy do
expect(scope.map(&:id)).to include(*Exercise.where(public: false, user_id: teacher.id).map(&:id)) expect(scope.map(&:id)).to include(*Exercise.where(public: false, user_id: teacher.id).map(&:id))
end end
it "includes all of team members' non-public exercises" do
expect(scope.map(&:id)).to include(*Exercise.where(public: false, team_id: teacher.teams.first.id).map(&:id))
end
it "does not include other authors' non-public exercises" do it "does not include other authors' non-public exercises" do
expect(scope.map(&:id)).not_to include(*Exercise.where(public: false).where("user_id <> #{teacher.id}").map(&:id)) expect(scope.map(&:id)).not_to include(*Exercise.where(public: false).where("team_id <> #{teacher.teams.first.id} AND user_id <> #{teacher.id}").map(&:id))
end end
end end
end end