Internalize private project minimum access level

Some feature allows GUEST to access only if project is not private.
This method returns access level when targeting private projects.
This commit is contained in:
Mark Chao 2019-11-14 10:50:19 +08:00
parent 03c0e9ba65
commit 2858452b68
3 changed files with 39 additions and 14 deletions

View file

@ -517,13 +517,11 @@ class Project < ApplicationRecord
# This scope returns projects where user has access to both the project and the feature. # This scope returns projects where user has access to both the project and the feature.
def self.filter_by_feature_visibility(feature, user) def self.filter_by_feature_visibility(feature, user)
scope = with_feature_available_for_user(feature, user) with_feature_available_for_user(feature, user)
.public_or_visible_to_user(
if ProjectFeature.guest_allowed_on_private_project?(feature) user,
scope.public_or_visible_to_user(user) ProjectFeature.required_minimum_access_level_for_private_project(feature)
else )
scope.public_or_visible_to_user(user, Gitlab::Access::REPORTER)
end
end end
scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') } scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') }

View file

@ -24,7 +24,7 @@ class ProjectFeature < ApplicationRecord
FEATURES = %i(issues merge_requests wiki snippets builds repository pages).freeze FEATURES = %i(issues merge_requests wiki snippets builds repository pages).freeze
PRIVATE_FEATURES_MIN_ACCESS_LEVEL = { merge_requests: Gitlab::Access::REPORTER }.freeze PRIVATE_FEATURES_MIN_ACCESS_LEVEL = { merge_requests: Gitlab::Access::REPORTER }.freeze
FEATURES_ALLOWED_BY_GUEST_ON_PRIVATE_PROJECT = %i(issues wiki).freeze PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT = { repository: Gitlab::Access::REPORTER }.freeze
STRING_OPTIONS = HashWithIndifferentAccess.new({ STRING_OPTIONS = HashWithIndifferentAccess.new({
'disabled' => DISABLED, 'disabled' => DISABLED,
'private' => PRIVATE, 'private' => PRIVATE,
@ -46,18 +46,21 @@ class ProjectFeature < ApplicationRecord
"#{table}.#{attribute}" "#{table}.#{attribute}"
end end
def guest_allowed_on_private_project?(feature)
feature = ensure_feature!(feature)
FEATURES_ALLOWED_BY_GUEST_ON_PRIVATE_PROJECT.include?(feature)
end
def required_minimum_access_level(feature) def required_minimum_access_level(feature)
feature = ensure_feature!(feature) feature = ensure_feature!(feature)
PRIVATE_FEATURES_MIN_ACCESS_LEVEL.fetch(feature, Gitlab::Access::GUEST) PRIVATE_FEATURES_MIN_ACCESS_LEVEL.fetch(feature, Gitlab::Access::GUEST)
end end
# Guest users can perform certain features on public and internal projects, but not private projects.
def required_minimum_access_level_for_private_project(feature)
feature = ensure_feature!(feature)
PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT.fetch(feature) do
required_minimum_access_level(feature)
end
end
def access_level_from_str(level) def access_level_from_str(level)
STRING_OPTIONS.fetch(level) STRING_OPTIONS.fetch(level)
end end

View file

@ -6,6 +6,16 @@ describe ProjectFeature do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
describe 'PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT' do
it 'has higher level than that of PRIVATE_FEATURES_MIN_ACCESS_LEVEL' do
described_class::PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT.each do |feature, level|
if generic_level = described_class::PRIVATE_FEATURES_MIN_ACCESS_LEVEL[feature]
expect(level).to be >= generic_level
end
end
end
end
describe '.quoted_access_level_column' do describe '.quoted_access_level_column' do
it 'returns the table name and quoted column name for a feature' do it 'returns the table name and quoted column name for a feature' do
expected = '"project_features"."issues_access_level"' expected = '"project_features"."issues_access_level"'
@ -246,10 +256,24 @@ describe ProjectFeature do
expect(described_class.required_minimum_access_level('merge_requests')).to eq(Gitlab::Access::REPORTER) expect(described_class.required_minimum_access_level('merge_requests')).to eq(Gitlab::Access::REPORTER)
end end
it 'handles repository' do
expect(described_class.required_minimum_access_level(:repository)).to eq(Gitlab::Access::GUEST)
end
it 'raises error if feature is invalid' do it 'raises error if feature is invalid' do
expect do expect do
described_class.required_minimum_access_level(:foos) described_class.required_minimum_access_level(:foos)
end.to raise_error end.to raise_error
end end
end end
describe '.required_minimum_access_level_for_private_project' do
it 'returns higher permission for repository' do
expect(described_class.required_minimum_access_level_for_private_project(:repository)).to eq(Gitlab::Access::REPORTER)
end
it 'returns normal permission for issues' do
expect(described_class.required_minimum_access_level_for_private_project(:issues)).to eq(Gitlab::Access::GUEST)
end
end
end end