Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/project_spec.rb')
-rw-r--r--spec/models/project_spec.rb412
1 files changed, 342 insertions, 70 deletions
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 4e38bf7d3e3..2fe50f8c48a 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Project, factory_default: :keep do
include GitHelpers
include ExternalAuthorizationServiceHelpers
include ReloadHelpers
+ include StubGitlabCalls
using RSpec::Parameterized::TableSyntax
let_it_be(:namespace) { create_default(:namespace).freeze }
@@ -379,6 +380,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:namespace_id) }
it { is_expected.to validate_length_of(:name).is_at_most(255) }
+ it { is_expected.not_to allow_value('colon:in:path').for(:path) } # This is to validate that a specially crafted name cannot bypass a pattern match. See !72555
it { is_expected.to validate_presence_of(:path) }
it { is_expected.to validate_length_of(:path).is_at_most(255) }
it { is_expected.to validate_length_of(:description).is_at_most(2000) }
@@ -1298,7 +1300,7 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#default_owner' do
+ describe '#first_owner' do
let_it_be(:owner) { create(:user) }
let_it_be(:namespace) { create(:namespace, owner: owner) }
@@ -1306,7 +1308,7 @@ RSpec.describe Project, factory_default: :keep do
let(:project) { build(:project, namespace: namespace) }
it 'is the namespace owner' do
- expect(project.default_owner).to eq(owner)
+ expect(project.first_owner).to eq(owner)
end
end
@@ -1315,9 +1317,9 @@ RSpec.describe Project, factory_default: :keep do
let(:project) { build(:project, group: group, namespace: namespace) }
it 'is the group owner' do
- allow(group).to receive(:default_owner).and_return(Object.new)
+ allow(group).to receive(:first_owner).and_return(Object.new)
- expect(project.default_owner).to eq(group.default_owner)
+ expect(project.first_owner).to eq(group.first_owner)
end
end
end
@@ -1358,51 +1360,51 @@ RSpec.describe Project, factory_default: :keep do
project.reload.has_external_issue_tracker
end
- it 'is false when external issue tracker service is not active' do
- create(:service, project: project, category: 'issue_tracker', active: false)
+ it 'is false when external issue tracker integration is not active' do
+ create(:integration, project: project, category: 'issue_tracker', active: false)
is_expected.to eq(false)
end
- it 'is false when other service is active' do
- create(:service, project: project, category: 'not_issue_tracker', active: true)
+ it 'is false when other integration is active' do
+ create(:integration, project: project, category: 'not_issue_tracker', active: true)
is_expected.to eq(false)
end
- context 'when there is an active external issue tracker service' do
- let!(:service) do
- create(:service, project: project, type: 'JiraService', category: 'issue_tracker', active: true)
+ context 'when there is an active external issue tracker integration' do
+ let!(:integration) do
+ create(:integration, project: project, type: 'JiraService', category: 'issue_tracker', active: true)
end
specify { is_expected.to eq(true) }
- it 'becomes false when external issue tracker service is destroyed' do
+ it 'becomes false when external issue tracker integration is destroyed' do
expect do
- Integration.find(service.id).delete
+ Integration.find(integration.id).delete
end.to change { subject }.to(false)
end
- it 'becomes false when external issue tracker service becomes inactive' do
+ it 'becomes false when external issue tracker integration becomes inactive' do
expect do
- service.update_column(:active, false)
+ integration.update_column(:active, false)
end.to change { subject }.to(false)
end
- context 'when there are two active external issue tracker services' do
- let_it_be(:second_service) do
- create(:service, project: project, type: 'CustomIssueTracker', category: 'issue_tracker', active: true)
+ context 'when there are two active external issue tracker integrations' do
+ let_it_be(:second_integration) do
+ create(:integration, project: project, type: 'CustomIssueTracker', category: 'issue_tracker', active: true)
end
- it 'does not become false when external issue tracker service is destroyed' do
+ it 'does not become false when external issue tracker integration is destroyed' do
expect do
- Integration.find(service.id).delete
+ Integration.find(integration.id).delete
end.not_to change { subject }
end
- it 'does not become false when external issue tracker service becomes inactive' do
+ it 'does not become false when external issue tracker integration becomes inactive' do
expect do
- service.update_column(:active, false)
+ integration.update_column(:active, false)
end.not_to change { subject }
end
end
@@ -1454,13 +1456,13 @@ RSpec.describe Project, factory_default: :keep do
specify { expect(has_external_wiki).to eq(true) }
- it 'becomes false if the external wiki service is destroyed' do
+ it 'becomes false if the external wiki integration is destroyed' do
expect do
Integration.find(integration.id).delete
end.to change { has_external_wiki }.to(false)
end
- it 'becomes false if the external wiki service becomes inactive' do
+ it 'becomes false if the external wiki integration becomes inactive' do
expect do
integration.update_column(:active, false)
end.to change { has_external_wiki }.to(false)
@@ -4580,11 +4582,25 @@ RSpec.describe Project, factory_default: :keep do
include ProjectHelpers
let_it_be(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, namespace: group) }
- let!(:project) { create(:project, project_level, namespace: group ) }
let(:user) { create_user_from_membership(project, membership) }
- context 'reporter level access' do
+ subject { described_class.filter_by_feature_visibility(feature, user) }
+
+ shared_examples 'filter respects visibility' do
+ it 'respects visibility' do
+ enable_admin_mode!(user) if admin_mode
+ project.update!(visibility_level: Gitlab::VisibilityLevel.level_value(project_level.to_s))
+ update_feature_access_level(project, feature_access_level)
+
+ expected_objects = expected_count == 1 ? [project] : []
+
+ expect(subject).to eq(expected_objects)
+ end
+ end
+
+ context 'with reporter level access' do
let(:feature) { MergeRequest }
where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
@@ -4592,20 +4608,11 @@ RSpec.describe Project, factory_default: :keep do
end
with_them do
- it "respects visibility" do
- enable_admin_mode!(user) if admin_mode
- update_feature_access_level(project, feature_access_level)
-
- expected_objects = expected_count == 1 ? [project] : []
-
- expect(
- described_class.filter_by_feature_visibility(feature, user)
- ).to eq(expected_objects)
- end
+ it_behaves_like 'filter respects visibility'
end
end
- context 'issues' do
+ context 'with feature issues' do
let(:feature) { Issue }
where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
@@ -4613,20 +4620,11 @@ RSpec.describe Project, factory_default: :keep do
end
with_them do
- it "respects visibility" do
- enable_admin_mode!(user) if admin_mode
- update_feature_access_level(project, feature_access_level)
-
- expected_objects = expected_count == 1 ? [project] : []
-
- expect(
- described_class.filter_by_feature_visibility(feature, user)
- ).to eq(expected_objects)
- end
+ it_behaves_like 'filter respects visibility'
end
end
- context 'wiki' do
+ context 'with feature wiki' do
let(:feature) { :wiki }
where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
@@ -4634,20 +4632,11 @@ RSpec.describe Project, factory_default: :keep do
end
with_them do
- it "respects visibility" do
- enable_admin_mode!(user) if admin_mode
- update_feature_access_level(project, feature_access_level)
-
- expected_objects = expected_count == 1 ? [project] : []
-
- expect(
- described_class.filter_by_feature_visibility(feature, user)
- ).to eq(expected_objects)
- end
+ it_behaves_like 'filter respects visibility'
end
end
- context 'code' do
+ context 'with feature code' do
let(:feature) { :repository }
where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
@@ -4655,16 +4644,7 @@ RSpec.describe Project, factory_default: :keep do
end
with_them do
- it "respects visibility" do
- enable_admin_mode!(user) if admin_mode
- update_feature_access_level(project, feature_access_level)
-
- expected_objects = expected_count == 1 ? [project] : []
-
- expect(
- described_class.filter_by_feature_visibility(feature, user)
- ).to eq(expected_objects)
- end
+ it_behaves_like 'filter respects visibility'
end
end
end
@@ -6835,7 +6815,7 @@ RSpec.describe Project, factory_default: :keep do
describe 'with integrations and chat names' do
subject { create(:project) }
- let(:integration) { create(:service, project: subject) }
+ let(:integration) { create(:integration, project: subject) }
before do
create_list(:chat_name, 5, integration: integration)
@@ -7476,6 +7456,258 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#enforced_runner_token_expiration_interval and #effective_runner_token_expiration_interval' do
+ shared_examples 'no enforced expiration interval' do
+ it { expect(subject.enforced_runner_token_expiration_interval).to be_nil }
+ end
+
+ shared_examples 'enforced expiration interval' do |enforced_interval:|
+ it { expect(subject.enforced_runner_token_expiration_interval).to eq(enforced_interval) }
+ end
+
+ shared_examples 'no effective expiration interval' do
+ it { expect(subject.effective_runner_token_expiration_interval).to be_nil }
+ end
+
+ shared_examples 'effective expiration interval' do |effective_interval:|
+ it { expect(subject.effective_runner_token_expiration_interval).to eq(effective_interval) }
+ end
+
+ context 'when there is no interval' do
+ let_it_be(:project) { create(:project) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'no effective expiration interval'
+ end
+
+ context 'when there is a project interval' do
+ let_it_be(:project) { create(:project, runner_token_expiration_interval: 3.days.to_i) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'effective expiration interval', effective_interval: 3.days
+ end
+
+ # runner_token_expiration_interval should not affect the expiration interval, only
+ # project_runner_token_expiration_interval should.
+ context 'when there is a site-wide enforced shared interval' do
+ before do
+ stub_application_setting(runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let_it_be(:project) { create(:project) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'no effective expiration interval'
+ end
+
+ # group_runner_token_expiration_interval should not affect the expiration interval, only
+ # project_runner_token_expiration_interval should.
+ context 'when there is a site-wide enforced group interval' do
+ before do
+ stub_application_setting(group_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let_it_be(:project) { create(:project) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'no effective expiration interval'
+ end
+
+ context 'when there is a site-wide enforced project interval' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let_it_be(:project) { create(:project) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 5.days
+ it_behaves_like 'effective expiration interval', effective_interval: 5.days
+ end
+
+ # runner_token_expiration_interval should not affect the expiration interval, only
+ # project_runner_token_expiration_interval should.
+ context 'when there is a group-enforced group interval' do
+ let_it_be(:group_settings) { create(:namespace_settings, runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'no effective expiration interval'
+ end
+
+ # subgroup_runner_token_expiration_interval should not affect the expiration interval, only
+ # project_runner_token_expiration_interval should.
+ context 'when there is a group-enforced subgroup interval' do
+ let_it_be(:group_settings) { create(:namespace_settings, subgroup_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'no effective expiration interval'
+ end
+
+ context 'when there is an owner group-enforced project interval' do
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 4.days
+ it_behaves_like 'effective expiration interval', effective_interval: 4.days
+ end
+
+ context 'when there is a grandparent group-enforced interval' do
+ let_it_be(:grandparent_group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 3.days.to_i) }
+ let_it_be(:grandparent_group) { create(:group, namespace_settings: grandparent_group_settings) }
+ let_it_be(:parent_group_settings) { create(:namespace_settings) }
+ let_it_be(:parent_group) { create(:group, parent: grandparent_group, namespace_settings: parent_group_settings) }
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, parent: parent_group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 3.days
+ it_behaves_like 'effective expiration interval', effective_interval: 3.days
+ end
+
+ context 'when there is a parent group-enforced interval overridden by group-enforced interval' do
+ let_it_be(:parent_group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 5.days.to_i) }
+ let_it_be(:parent_group) { create(:group, namespace_settings: parent_group_settings) }
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, parent: parent_group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 4.days
+ it_behaves_like 'effective expiration interval', effective_interval: 4.days
+ end
+
+ context 'when site-wide enforced interval overrides project interval' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 3.days.to_i)
+ end
+
+ let_it_be(:project) { create(:project, runner_token_expiration_interval: 4.days.to_i) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 3.days
+ it_behaves_like 'effective expiration interval', effective_interval: 3.days
+ end
+
+ context 'when project interval overrides site-wide enforced interval' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let_it_be(:project) { create(:project, runner_token_expiration_interval: 4.days.to_i) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 5.days
+ it_behaves_like 'effective expiration interval', effective_interval: 4.days
+
+ it 'has human-readable expiration intervals' do
+ expect(subject.enforced_runner_token_expiration_interval_human_readable).to eq('5d')
+ expect(subject.effective_runner_token_expiration_interval_human_readable).to eq('4d')
+ end
+ end
+
+ context 'when site-wide enforced interval overrides group-enforced interval' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 3.days.to_i)
+ end
+
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 3.days
+ it_behaves_like 'effective expiration interval', effective_interval: 3.days
+ end
+
+ context 'when group-enforced interval overrides site-wide enforced interval' do
+ before do
+ stub_application_setting(project_runner_token_expiration_interval: 5.days.to_i)
+ end
+
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 4.days
+ it_behaves_like 'effective expiration interval', effective_interval: 4.days
+ end
+
+ context 'when group-enforced interval overrides project interval' do
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 3.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group, runner_token_expiration_interval: 4.days.to_i) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 3.days
+ it_behaves_like 'effective expiration interval', effective_interval: 3.days
+ end
+
+ context 'when project interval overrides group-enforced interval' do
+ let_it_be(:group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 5.days.to_i) }
+ let_it_be(:group) { create(:group, namespace_settings: group_settings) }
+ let_it_be(:project) { create(:project, group: group, runner_token_expiration_interval: 4.days.to_i) }
+
+ subject { project }
+
+ it_behaves_like 'enforced expiration interval', enforced_interval: 5.days
+ it_behaves_like 'effective expiration interval', effective_interval: 4.days
+ end
+
+ # Unrelated groups should not affect the expiration interval.
+ context 'when there is an enforced project interval in an unrelated group' do
+ let_it_be(:unrelated_group_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:unrelated_group) { create(:group, namespace_settings: unrelated_group_settings) }
+ let_it_be(:project) { create(:project) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'no effective expiration interval'
+ end
+
+ # Subgroups should not affect the parent group expiration interval.
+ context 'when there is an enforced project interval in a subgroup' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup_settings) { create(:namespace_settings, project_runner_token_expiration_interval: 4.days.to_i) }
+ let_it_be(:subgroup) { create(:group, parent: group, namespace_settings: subgroup_settings) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ subject { project }
+
+ it_behaves_like 'no enforced expiration interval'
+ it_behaves_like 'no effective expiration interval'
+ end
+ end
+
it_behaves_like 'it has loose foreign keys' do
let(:factory_name) { :project }
end
@@ -7551,6 +7783,46 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#context_commits_enabled?' do
+ let_it_be(:project) { create(:project) }
+
+ subject(:result) { project.context_commits_enabled? }
+
+ context 'when context_commits feature flag is enabled' do
+ before do
+ stub_feature_flags(context_commits: true)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when context_commits feature flag is disabled' do
+ before do
+ stub_feature_flags(context_commits: false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when context_commits feature flag is enabled on this project' do
+ before do
+ stub_feature_flags(context_commits: project)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when context_commits feature flag is enabled on another project' do
+ let(:another_project) { create(:project) }
+
+ before do
+ stub_feature_flags(context_commits: another_project)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
private
def finish_job(export_job)