From 6fa5f510e83a91e19a1601bf6c01a9cffe6fd5c9 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 25 Aug 2019 07:20:17 -0700 Subject: [PATCH] Guard against deleted project feature entry In https://gitlab.com/gitlab-org/gitlab-ce/issues/66482, we see that a project's `project_feature` association may be lazily loaded and hence return `nil` if the entry is deleted if the `Project` is already loaded in memory. To ensure we don't fail hard when this happens, assume all features are disabled. We can fix this issue by eager loading the `project_feature` in https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/32169, but we shouldn't have to depend on that. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/66482 --- app/policies/project_policy.rb | 2 ++ .../sh-guard-against-orphaned-project-feature.yml | 5 +++++ spec/policies/project_policy_spec.rb | 13 +++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 changelogs/unreleased/sh-guard-against-orphaned-project-feature.yml diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index b8dee1b0789..e2634692dc7 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -502,6 +502,8 @@ class ProjectPolicy < BasePolicy end def feature_available?(feature) + return false unless project.project_feature + case project.project_feature.access_level(feature) when ProjectFeature::DISABLED false diff --git a/changelogs/unreleased/sh-guard-against-orphaned-project-feature.yml b/changelogs/unreleased/sh-guard-against-orphaned-project-feature.yml new file mode 100644 index 00000000000..99c8732c5b0 --- /dev/null +++ b/changelogs/unreleased/sh-guard-against-orphaned-project-feature.yml @@ -0,0 +1,5 @@ +--- +title: Guard against deleted project feature entry in project permissions +merge_request: 32187 +author: +type: fixed diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 8fd54e0bf1d..71ba73d5661 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -94,6 +94,19 @@ describe ProjectPolicy do permissions.each { |p| is_expected.not_to be_allowed(p) } end + context 'with no project feature' do + subject { described_class.new(owner, project) } + + before do + project.project_feature.destroy + project.reload + end + + it 'returns false' do + is_expected.to be_disallowed(:read_build) + end + end + it 'does not include the read_issue permission when the issue author is not a member of the private project' do project = create(:project, :private) issue = create(:issue, project: project, author: create(:user))