2019-07-07 11:18:12 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-09-29 09:46:39 +05:30
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
describe ProjectFeature do
|
2017-09-10 17:25:29 +05:30
|
|
|
let(:project) { create(:project) }
|
2016-09-29 09:46:39 +05:30
|
|
|
let(:user) { create(:user) }
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
describe '.quoted_access_level_column' do
|
|
|
|
it 'returns the table name and quoted column name for a feature' do
|
|
|
|
expected = if Gitlab::Database.postgresql?
|
|
|
|
'"project_features"."issues_access_level"'
|
|
|
|
else
|
|
|
|
'`project_features`.`issues_access_level`'
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(described_class.quoted_access_level_column(:issues)).to eq(expected)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-29 09:46:39 +05:30
|
|
|
describe '#feature_available?' do
|
2018-12-05 23:21:45 +05:30
|
|
|
let(:features) { %w(issues wiki builds merge_requests snippets repository pages) }
|
2016-09-29 09:46:39 +05:30
|
|
|
|
|
|
|
context 'when features are disabled' do
|
|
|
|
it "returns false" do
|
|
|
|
features.each do |feature|
|
|
|
|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::DISABLED)
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when features are enabled only for team members' do
|
|
|
|
it "returns false when user is not a team member" do
|
|
|
|
features.each do |feature|
|
|
|
|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::PRIVATE)
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns true when user is a team member" do
|
2018-03-17 18:26:18 +05:30
|
|
|
project.add_developer(user)
|
2016-09-29 09:46:39 +05:30
|
|
|
|
|
|
|
features.each do |feature|
|
|
|
|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::PRIVATE)
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns true when user is a member of project group" do
|
|
|
|
group = create(:group)
|
2017-09-10 17:25:29 +05:30
|
|
|
project = create(:project, namespace: group)
|
2016-09-29 09:46:39 +05:30
|
|
|
group.add_developer(user)
|
|
|
|
|
|
|
|
features.each do |feature|
|
|
|
|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::PRIVATE)
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns true if user is an admin" do
|
|
|
|
user.update_attribute(:admin, true)
|
|
|
|
|
|
|
|
features.each do |feature|
|
|
|
|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::PRIVATE)
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when feature is enabled for everyone' do
|
|
|
|
it "returns true" do
|
|
|
|
features.each do |feature|
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-12-05 23:21:45 +05:30
|
|
|
|
|
|
|
context 'when feature is disabled by a feature flag' do
|
|
|
|
it 'returns false' do
|
|
|
|
stub_feature_flags(issues: false)
|
|
|
|
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when feature is enabled by a feature flag' do
|
|
|
|
it 'returns true' do
|
|
|
|
stub_feature_flags(issues: true)
|
|
|
|
|
|
|
|
expect(project.feature_available?(:issues, user)).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
2016-09-29 09:46:39 +05:30
|
|
|
end
|
|
|
|
|
2016-11-03 12:29:30 +05:30
|
|
|
context 'repository related features' do
|
|
|
|
before do
|
2018-11-18 11:00:15 +05:30
|
|
|
project.project_feature.update(
|
2016-11-03 12:29:30 +05:30
|
|
|
merge_requests_access_level: ProjectFeature::DISABLED,
|
|
|
|
builds_access_level: ProjectFeature::DISABLED,
|
|
|
|
repository_access_level: ProjectFeature::PRIVATE
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not allow repository related features have higher level" do
|
|
|
|
features = %w(builds merge_requests)
|
|
|
|
project_feature = project.project_feature
|
|
|
|
|
|
|
|
features.each do |feature|
|
|
|
|
field = "#{feature}_access_level".to_sym
|
|
|
|
project_feature.update_attribute(field, ProjectFeature::ENABLED)
|
|
|
|
expect(project_feature.valid?).to be_falsy
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-12-05 23:21:45 +05:30
|
|
|
context 'public features' do
|
|
|
|
it "does not allow public for other than pages" do
|
|
|
|
features = %w(issues wiki builds merge_requests snippets repository)
|
|
|
|
project_feature = project.project_feature
|
|
|
|
|
|
|
|
features.each do |feature|
|
|
|
|
field = "#{feature}_access_level".to_sym
|
|
|
|
project_feature.update_attribute(field, ProjectFeature::PUBLIC)
|
|
|
|
expect(project_feature.valid?).to be_falsy
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-29 09:46:39 +05:30
|
|
|
describe '#*_enabled?' do
|
|
|
|
let(:features) { %w(wiki builds merge_requests) }
|
|
|
|
|
|
|
|
it "returns false when feature is disabled" do
|
|
|
|
features.each do |feature|
|
|
|
|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::DISABLED)
|
|
|
|
expect(project.public_send("#{feature}_enabled?")).to eq(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns true when feature is enabled only for team members" do
|
|
|
|
features.each do |feature|
|
|
|
|
project.project_feature.update_attribute("#{feature}_access_level".to_sym, ProjectFeature::PRIVATE)
|
|
|
|
expect(project.public_send("#{feature}_enabled?")).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns true when feature is enabled for everyone" do
|
|
|
|
features.each do |feature|
|
|
|
|
expect(project.public_send("#{feature}_enabled?")).to eq(true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-09-30 21:07:59 +05:30
|
|
|
|
|
|
|
describe 'default pages access level' do
|
|
|
|
subject { project.project_feature.pages_access_level }
|
|
|
|
|
|
|
|
before do
|
|
|
|
# project factory overrides all values in project_feature after creation
|
|
|
|
project.project_feature.destroy!
|
|
|
|
project.build_project_feature.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when new project is private' do
|
|
|
|
let(:project) { create(:project, :private) }
|
|
|
|
|
|
|
|
it { is_expected.to eq(ProjectFeature::PRIVATE) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when new project is internal' do
|
|
|
|
let(:project) { create(:project, :internal) }
|
|
|
|
|
|
|
|
it { is_expected.to eq(ProjectFeature::PRIVATE) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when new project is public' do
|
|
|
|
let(:project) { create(:project, :public) }
|
|
|
|
|
|
|
|
it { is_expected.to eq(ProjectFeature::ENABLED) }
|
|
|
|
end
|
|
|
|
end
|
2019-10-03 12:08:05 +05:30
|
|
|
|
|
|
|
describe '.required_minimum_access_level' do
|
|
|
|
it 'handles reporter level' do
|
|
|
|
expect(described_class.required_minimum_access_level(:merge_requests)).to eq(Gitlab::Access::REPORTER)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'handles guest level' do
|
|
|
|
expect(described_class.required_minimum_access_level(:issues)).to eq(Gitlab::Access::GUEST)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'accepts ActiveModel' do
|
|
|
|
expect(described_class.required_minimum_access_level(MergeRequest)).to eq(Gitlab::Access::REPORTER)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'accepts string' do
|
|
|
|
expect(described_class.required_minimum_access_level('merge_requests')).to eq(Gitlab::Access::REPORTER)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'raises error if feature is invalid' do
|
|
|
|
expect do
|
|
|
|
described_class.required_minimum_access_level(:foos)
|
|
|
|
end.to raise_error
|
|
|
|
end
|
|
|
|
end
|
2016-09-29 09:46:39 +05:30
|
|
|
end
|