diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-23 03:10:18 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-23 03:10:18 +0300 |
commit | 2994a84f0137ecf313e87bd3a79f433ab615f984 (patch) | |
tree | 082e6125a63b0e93667738637aa5e27359c85364 /spec | |
parent | 6c68583a42998b0bb15971785f372197bfc55cd7 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
20 files changed, 439 insertions, 132 deletions
diff --git a/spec/factories/namespace_package_settings.rb b/spec/factories/namespace_package_settings.rb index 33f290d0a2d..8c5f7193cde 100644 --- a/spec/factories/namespace_package_settings.rb +++ b/spec/factories/namespace_package_settings.rb @@ -15,6 +15,9 @@ FactoryBot.define do nuget_symbol_server_enabled { false } + terraform_module_duplicates_allowed { false } + terraform_module_duplicate_exception_regex { 'foo' } + trait :group do namespace { association(:group) } end diff --git a/spec/frontend/vue_shared/components/segmented_control_button_group_spec.js b/spec/frontend/vue_shared/components/segmented_control_button_group_spec.js index 623a8739907..a3bf3ca23e3 100644 --- a/spec/frontend/vue_shared/components/segmented_control_button_group_spec.js +++ b/spec/frontend/vue_shared/components/segmented_control_button_group_spec.js @@ -122,6 +122,7 @@ describe('~/vue_shared/components/segmented_control_button_group.vue', () => { [[{ value: '1' }]], [[{ value: 1, disabled: true }]], [[{ value: true, disabled: false }]], + [[{ value: true, props: { 'data-testid': 'test' } }]], ])('with options=%j, passes validation', (options) => { createComponent({ options }); diff --git a/spec/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/graphql/mutations/namespace/package_settings/update_spec.rb index b184baaca3e..f5bd9ad93be 100644 --- a/spec/graphql/mutations/namespace/package_settings/update_spec.rb +++ b/spec/graphql/mutations/namespace/package_settings/update_spec.rb @@ -39,7 +39,9 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update, feature_category: lock_npm_package_requests_forwarding: false, pypi_package_requests_forwarding: nil, lock_pypi_package_requests_forwarding: false, - nuget_symbol_server_enabled: false + nuget_symbol_server_enabled: false, + terraform_module_duplicates_allowed: false, + terraform_module_duplicate_exception_regex: 'foo' }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE', @@ -53,7 +55,9 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update, feature_category: lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, lock_pypi_package_requests_forwarding: true, - nuget_symbol_server_enabled: true + nuget_symbol_server_enabled: true, + terraform_module_duplicates_allowed: true, + terraform_module_duplicate_exception_regex: 'bar' } it_behaves_like 'returning a success' @@ -109,7 +113,9 @@ RSpec.describe Mutations::Namespace::PackageSettings::Update, feature_category: lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, lock_pypi_package_requests_forwarding: true, - nuget_symbol_server_enabled: true + nuget_symbol_server_enabled: true, + terraform_module_duplicates_allowed: true, + terraform_module_duplicate_exception_regex: 'bar' } end diff --git a/spec/graphql/types/namespace/package_settings_type_spec.rb b/spec/graphql/types/namespace/package_settings_type_spec.rb index 0e731c1e2bf..0e958aca586 100644 --- a/spec/graphql/types/namespace/package_settings_type_spec.rb +++ b/spec/graphql/types/namespace/package_settings_type_spec.rb @@ -33,6 +33,8 @@ RSpec.describe GitlabSchema.types['PackageSettings'], feature_category: :package npm_package_requests_forwarding_locked pypi_package_requests_forwarding_locked nuget_symbol_server_enabled + terraform_module_duplicates_allowed + terraform_module_duplicate_exception_regex ] expect(described_class).to include_graphql_fields(*expected_fields) diff --git a/spec/lib/api/entities/group_spec.rb b/spec/lib/api/entities/group_spec.rb new file mode 100644 index 00000000000..270ac323c7d --- /dev/null +++ b/spec/lib/api/entities/group_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Entities::Group, feature_category: :groups_and_projects do + let_it_be(:group) do + base_group = create(:group) { |g| create(:project_statistics, namespace_id: g.id) } + Group.with_statistics.find(base_group.id) + end + + subject(:json) { described_class.new(group, { with_custom_attributes: true, statistics: true }).as_json } + + it 'returns expected data' do + expect(json.keys).to( + include( + :organization_id, :path, :description, :visibility, :share_with_group_lock, :require_two_factor_authentication, + :two_factor_grace_period, :project_creation_level, :auto_devops_enabled, + :subgroup_creation_level, :emails_disabled, :emails_enabled, :lfs_enabled, :default_branch_protection, + :default_branch_protection_defaults, :avatar_url, :request_access_enabled, :full_name, :full_path, :created_at, + :parent_id, :organization_id, :shared_runners_setting, :custom_attributes, :statistics + ) + ) + end +end diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb index c76694b60d3..d1dee70e34d 100644 --- a/spec/lib/api/helpers_spec.rb +++ b/spec/lib/api/helpers_spec.rb @@ -406,6 +406,37 @@ RSpec.describe API::Helpers, feature_category: :shared do end end + describe '#find_organization!' do + let_it_be(:organization) { create(:organization) } + let_it_be(:user) { create(:user) } + + before do + allow(helper).to receive(:current_user).and_return(user) + allow(helper).to receive(:initial_current_user).and_return(user) + end + + context 'when user is authenticated' do + it 'returns requested organization' do + expect(helper.find_organization!(organization.id)).to eq(organization) + end + end + + context 'when user is not authenticated' do + let(:user) { nil } + + it 'returns requested organization' do + expect(helper.find_organization!(organization.id)).to eq(organization) + end + end + + context 'when organization does not exist' do + it 'returns nil' do + expect(helper).to receive(:render_api_error!).with('404 Organization Not Found', 404) + expect(helper.find_organization!(non_existing_record_id)).to be_nil + end + end + end + describe '#find_group!' do let_it_be(:group) { create(:group, :public) } let_it_be(:user) { create(:user) } @@ -457,7 +488,7 @@ RSpec.describe API::Helpers, feature_category: :shared do end end - context 'support for IDs and paths as arguments' do + context 'with support for IDs and paths as arguments' do let_it_be(:group) { create(:group) } let(:user) { group.first_owner } @@ -505,6 +536,34 @@ RSpec.describe API::Helpers, feature_category: :shared do end end + context 'with support for organization as an argument' do + let_it_be(:group) { create(:group) } + let_it_be(:organization) { create(:organization) } + + before do + allow(helper).to receive(:current_user).and_return(group.first_owner) + allow(helper).to receive(:job_token_authentication?).and_return(false) + allow(helper).to receive(:authenticate_non_public?).and_return(false) + end + + subject { helper.find_group!(group.id, organization: organization) } + + context 'when group exists in the organization' do + before do + group.update!(organization: organization) + end + + it { is_expected.to eq(group) } + end + + context 'when group does not exist in the organization' do + it 'returns nil' do + expect(helper).to receive(:render_api_error!).with('404 Group Not Found', 404) + is_expected.to be_nil + end + end + end + describe '#find_group_by_full_path!' do let_it_be(:group) { create(:group, :public) } let_it_be(:user) { create(:user) } diff --git a/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb index 8d6415b8179..8b6d628833e 100644 --- a/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb +++ b/spec/lib/gitlab/legacy_github_import/comment_formatter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do +RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter, feature_category: :importers do let_it_be(:project) { create(:project) } let(:client) { double } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } } @@ -76,12 +76,6 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do context 'when author is a GitLab user' do let(:raw) { base.merge(user: octocat) } - it 'returns GitLab user id associated with GitHub id as author_id' do - gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') - - expect(comment.attributes.fetch(:author_id)).to eq gl_user.id - end - it 'returns GitLab user id associated with GitHub email as author_id' do gl_user = create(:user, email: octocat[:email]) @@ -89,7 +83,7 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do end it 'returns note without created at tag line' do - create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') + create(:user, email: octocat[:email]) expect(comment.attributes.fetch(:note)).to eq("I'm having a problem with this.") end diff --git a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb index d3548fecbcd..9baf234b14b 100644 --- a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb +++ b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do +RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter, feature_category: :importers do let_it_be(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) } let(:client) { double } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } } @@ -82,12 +82,6 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do expect(issue.attributes.fetch(:assignee_ids)).to be_empty end - it 'returns GitLab user id associated with GitHub id as assignee_id' do - gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') - - expect(issue.attributes.fetch(:assignee_ids)).to eq [gl_user.id] - end - it 'returns GitLab user id associated with GitHub email as assignee_id' do gl_user = create(:user, email: octocat[:email]) @@ -117,12 +111,6 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do expect(issue.attributes.fetch(:author_id)).to eq project.creator_id end - it 'returns GitLab user id associated with GitHub id as author_id' do - gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') - - expect(issue.attributes.fetch(:author_id)).to eq gl_user.id - end - it 'returns GitLab user id associated with GitHub email as author_id' do gl_user = create(:user, email: octocat[:email]) @@ -130,7 +118,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do end it 'returns description without created at tag line' do - create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') + create(:user, email: octocat[:email]) expect(issue.attributes.fetch(:description)).to eq("I'm having a problem with this.") end diff --git a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb index 90469693820..1555e3e0d4c 100644 --- a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb +++ b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do +RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter, feature_category: :importers do let_it_be(:project) { create(:project, :repository) } let(:client) { double } let(:source_sha) { create(:commit, project: project).id } @@ -136,12 +136,6 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do expect(pull_request.attributes.fetch(:assignee_id)).to be_nil end - it 'returns GitLab user id associated with GitHub id as assignee_id' do - gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') - - expect(pull_request.attributes.fetch(:assignee_id)).to eq gl_user.id - end - it 'returns GitLab user id associated with GitHub email as assignee_id' do gl_user = create(:user, email: octocat[:email]) @@ -156,12 +150,6 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do expect(pull_request.attributes.fetch(:author_id)).to eq project.creator_id end - it 'returns GitLab user id associated with GitHub id as author_id' do - gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') - - expect(pull_request.attributes.fetch(:author_id)).to eq gl_user.id - end - it 'returns GitLab user id associated with GitHub email as author_id' do gl_user = create(:user, email: octocat[:email]) @@ -169,7 +157,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do end it 'returns description without created at tag line' do - create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') + create(:user, email: octocat[:email]) expect(pull_request.attributes.fetch(:description)).to eq('Please pull these awesome changes') end diff --git a/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb index 0844ab7eccc..d387d79aa30 100644 --- a/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb +++ b/spec/lib/gitlab/legacy_github_import/user_formatter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::LegacyGithubImport::UserFormatter do +RSpec.describe Gitlab::LegacyGithubImport::UserFormatter, feature_category: :importers do let(:client) { double } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } } let(:gitea_ghost) { { id: -1, login: 'Ghost', email: '' } } @@ -15,12 +15,6 @@ RSpec.describe Gitlab::LegacyGithubImport::UserFormatter do end context 'when GitHub user is a GitLab user' do - it 'return GitLab user id when user associated their account with GitHub' do - gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github') - - expect(user.gitlab_id).to eq gl_user.id - end - it 'returns GitLab user id when user confirmed primary email matches GitHub email' do gl_user = create(:user, email: octocat[:email]) diff --git a/spec/migrations/20231204095802_change_i_code_review_create_mr_keys_from_redis_hll_to_redis_spec.rb b/spec/migrations/20231204095802_change_i_code_review_create_mr_keys_from_redis_hll_to_redis_spec.rb deleted file mode 100644 index 25ca0936dbe..00000000000 --- a/spec/migrations/20231204095802_change_i_code_review_create_mr_keys_from_redis_hll_to_redis_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' -require_migration! - -RSpec.describe ChangeICodeReviewCreateMrKeysFromRedisHllToRedis, :migration, :clean_gitlab_redis_cache, feature_category: :service_ping do - def set_redis_hll(key, value) - Gitlab::Redis::HLL.add(key: key, value: value, expiry: 6.weeks) - end - - def get_int_from_redis(key) - Gitlab::Redis::SharedState.with { |redis| redis.get(key)&.to_i } - end - - describe "#up" do - before do - set_redis_hll('{hll_counters}_i_code_review_create_mr-2023-16', 1) - set_redis_hll('{hll_counters}_i_code_review_create_mr-2023-16', 2) - set_redis_hll('{hll_counters}_i_code_review_create_mr-2023-47', 3) - set_redis_hll('{hll_counters}_i_code_review_create_mr-2023-48', 1) - set_redis_hll('{hll_counters}_i_code_review_create_mr-2023-49', 2) - set_redis_hll('{hll_counters}_i_code_review_create_mr-2023-49', 4) - set_redis_hll('{hll_counters}_some_other_event-2023-49', 7) - end - - it 'migrates all RedisHLL keys for i_code_review_create_mr', :aggregate_failures do - migrate! - - expect(get_int_from_redis('{event_counters}_i_code_review_user_create_mr-2023-16')).to eq(2) - expect(get_int_from_redis('{event_counters}_i_code_review_user_create_mr-2023-47')).to eq(1) - expect(get_int_from_redis('{event_counters}_i_code_review_user_create_mr-2023-48')).to eq(1) - expect(get_int_from_redis('{event_counters}_i_code_review_user_create_mr-2023-49')).to eq(2) - end - - it 'does not not migrate other RedisHLL keys' do - migrate! - - expect(get_int_from_redis('{event_counters}_some_other_event-2023-16')).to be_nil - end - end -end diff --git a/spec/models/namespace/package_setting_spec.rb b/spec/models/namespace/package_setting_spec.rb index f06490d7999..e326e8cace8 100644 --- a/spec/models/namespace/package_setting_spec.rb +++ b/spec/models/namespace/package_setting_spec.rb @@ -12,13 +12,21 @@ RSpec.describe Namespace::PackageSetting, feature_category: :package_registry do describe '#maven_duplicates_allowed' do it { is_expected.to validate_inclusion_of(:maven_duplicates_allowed).in_array([true, false]) } - it { is_expected.to validate_inclusion_of(:generic_duplicates_allowed).in_array([true, false]) } - it { is_expected.to validate_inclusion_of(:nuget_duplicates_allowed).in_array([true, false]) } + it { is_expected.to validate_length_of(:maven_duplicate_exception_regex).is_at_most(255) } end it { is_expected.to allow_value(true, false).for(:nuget_symbol_server_enabled) } it { is_expected.not_to allow_value(nil).for(:nuget_symbol_server_enabled) } + it { is_expected.to validate_inclusion_of(:generic_duplicates_allowed).in_array([true, false]) } + it { is_expected.to validate_length_of(:generic_duplicate_exception_regex).is_at_most(255) } + it { is_expected.to validate_inclusion_of(:nuget_duplicates_allowed).in_array([true, false]) } + it { is_expected.to validate_length_of(:nuget_duplicate_exception_regex).is_at_most(255) } + + it { is_expected.to allow_value(true, false).for(:terraform_module_duplicates_allowed) } + it { is_expected.not_to allow_value(nil).for(:terraform_module_duplicates_allowed) } + it { is_expected.to validate_length_of(:terraform_module_duplicate_exception_regex).is_at_most(255) } + describe 'regex values' do let_it_be(:package_settings) { create(:namespace_package_setting) } @@ -39,6 +47,50 @@ RSpec.describe Namespace::PackageSetting, feature_category: :package_registry do end end + describe 'scopes' do + describe '.namespace_id_in' do + let_it_be(:package_settings) { create(:namespace_package_setting) } + let_it_be(:other_package_settings) { create(:namespace_package_setting) } + + subject { described_class.namespace_id_in([package_settings.namespace_id]) } + + it { is_expected.to eq([package_settings]) } + end + + describe '.with_terraform_module_duplicates_allowed_or_exception_regex' do + let_it_be(:package_settings) { create(:namespace_package_setting) } + + subject { described_class.with_terraform_module_duplicates_allowed_or_exception_regex } + + context 'when terraform_module_duplicates_allowed is true' do + before do + package_settings.update_column(:terraform_module_duplicates_allowed, true) + end + + it { is_expected.to eq([package_settings]) } + end + + context 'when terraform_module_duplicate_exception_regex is present' do + before do + package_settings.update_column(:terraform_module_duplicate_exception_regex, 'foo') + end + + it { is_expected.to eq([package_settings]) } + end + + context 'when terraform_module_duplicates_allowed is false and terraform_module_duplicate_exception_regex is empty' do + before do + package_settings.update_columns( + terraform_module_duplicates_allowed: false, + terraform_module_duplicate_exception_regex: '' + ) + end + + it { is_expected.to be_empty } + end + end + end + describe '#duplicates_allowed?' do using RSpec::Parameterized::TableSyntax @@ -46,9 +98,14 @@ RSpec.describe Namespace::PackageSetting, feature_category: :package_registry do context 'package types with package_settings' do # As more package types gain settings they will be added to this list - %i[maven_package generic_package nuget_package].each do |format| - context "with package_type:#{format}" do - let_it_be(:package) { create(format, name: 'foo', version: '1.0.0-beta') } + [ + { format: :maven_package, package_name: 'foo' }, + { format: :generic_package, package_name: 'foo' }, + { format: :nuget_package, package_name: 'foo' }, + { format: :terraform_module_package, package_name: 'foo/bar' } + ].each do |type| + context "with package_type: #{type[:format]}" do + let_it_be(:package) { create(type[:format], name: type[:package_name], version: '1.0.0-beta') } let_it_be(:package_type) { package.package_type } let_it_be(:package_setting) { package.project.namespace.package_settings } @@ -61,7 +118,7 @@ RSpec.describe Namespace::PackageSetting, feature_category: :package_registry do end with_them do - context "for #{format}" do + context "for #{type[:format]}" do before do package_setting.update!( "#{package_type}_duplicates_allowed" => duplicates_allowed, diff --git a/spec/policies/organizations/organization_policy_spec.rb b/spec/policies/organizations/organization_policy_spec.rb index 7eed497d644..a1a2f1db305 100644 --- a/spec/policies/organizations/organization_policy_spec.rb +++ b/spec/policies/organizations/organization_policy_spec.rb @@ -20,6 +20,7 @@ RSpec.describe Organizations::OrganizationPolicy, feature_category: :cell do context 'when admin mode is enabled', :enable_admin_mode do it { is_expected.to be_allowed(:admin_organization) } + it { is_expected.to be_allowed(:create_group) } it { is_expected.to be_allowed(:read_organization) } it { is_expected.to be_allowed(:read_organization_user) } end @@ -36,12 +37,14 @@ RSpec.describe Organizations::OrganizationPolicy, feature_category: :cell do end it { is_expected.to be_allowed(:admin_organization) } + it { is_expected.to be_allowed(:create_group) } it { is_expected.to be_allowed(:read_organization) } it { is_expected.to be_allowed(:read_organization_user) } end context 'when the user is not part of the organization' do it { is_expected.to be_disallowed(:admin_organization) } + it { is_expected.to be_disallowed(:create_group) } it { is_expected.to be_disallowed(:read_organization_user) } # All organizations are currently public, and hence they are allowed to be read # even if the user is not a part of the organization. diff --git a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb index 05c1a2d96d9..7c5d86b9f5c 100644 --- a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb +++ b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb @@ -23,7 +23,9 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, lock_pypi_package_requests_forwarding: true, - nuget_symbol_server_enabled: true + nuget_symbol_server_enabled: true, + terraform_module_duplicates_allowed: true, + terraform_module_duplicate_exception_regex: 'foo-.*' } end @@ -44,6 +46,8 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis pypiPackageRequestsForwarding lockPypiPackageRequestsForwarding nugetSymbolServerEnabled + terraformModuleDuplicatesAllowed + terraformModuleDuplicateExceptionRegex } errors QL @@ -73,6 +77,8 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis expect(package_settings_response['npmPackageRequestsForwarding']).to eq(params[:npm_package_requests_forwarding]) expect(package_settings_response['lockNpmPackageRequestsForwarding']).to eq(params[:lock_npm_package_requests_forwarding]) expect(package_settings_response['nugetSymbolServerEnabled']).to eq(params[:nuget_symbol_server_enabled]) + expect(package_settings_response['terraformModuleDuplicatesAllowed']).to eq(params[:terraform_module_duplicates_allowed]) + expect(package_settings_response['terraformModuleDuplicateExceptionRegex']).to eq(params[:terraform_module_duplicate_exception_regex]) end end @@ -115,7 +121,9 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis lock_npm_package_requests_forwarding: false, pypi_package_requests_forwarding: nil, lock_pypi_package_requests_forwarding: false, - nuget_symbol_server_enabled: false + nuget_symbol_server_enabled: false, + terraform_module_duplicates_allowed: false, + terraform_module_duplicate_exception_regex: 'foo' }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'foo-.*', @@ -129,7 +137,9 @@ RSpec.describe 'Updating the package settings', feature_category: :package_regis lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, lock_pypi_package_requests_forwarding: true, - nuget_symbol_server_enabled: true + nuget_symbol_server_enabled: true, + terraform_module_duplicates_allowed: true, + terraform_module_duplicate_exception_regex: 'foo-.*' } it_behaves_like 'returning a success' diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 327dfd0a76b..d1158cba16e 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -1937,6 +1937,59 @@ RSpec.describe API::Groups, feature_category: :groups_and_projects do end end + context 'when group is within a provided organization' do + let_it_be(:organization) { create(:organization) } + + context 'when user is an organization user' do + before_all do + create(:organization_user, user: user3, organization: organization) + end + + it 'creates group within organization' do + post api('/groups', user3), params: attributes_for_group_api(organization_id: organization.id) + + expect(response).to have_gitlab_http_status(:created) + expect(json_response['organization_id']).to eq(organization.id) + end + + context 'when parent_group is not part of the organization' do + it 'does not create the group with not_found' do + post( + api('/groups', user3), + params: attributes_for_group_api(parent_id: group2.id, organization_id: organization.id) + ) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'when organization does not exist' do + it 'does not create the group with not_found' do + post api('/groups', user3), params: attributes_for_group_api(organization_id: non_existing_record_id) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when user is not an organization user' do + it 'does not create the group' do + post api('/groups', user3), params: attributes_for_group_api(organization_id: organization.id) + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context 'when user is an admin' do + it 'creates group within organization' do + post api('/groups', admin, admin_mode: true), params: attributes_for_group_api(organization_id: organization.id) + + expect(response).to have_gitlab_http_status(:created) + expect(json_response['organization_id']).to eq(organization.id) + end + end + end + context "when authenticated as user with group permissions" do it "creates group", :aggregate_failures do group = attributes_for_group_api request_access_enabled: false diff --git a/spec/requests/api/terraform/modules/v1/project_packages_spec.rb b/spec/requests/api/terraform/modules/v1/project_packages_spec.rb index 3377f8d6647..70f7ec64d40 100644 --- a/spec/requests/api/terraform/modules/v1/project_packages_spec.rb +++ b/spec/requests/api/terraform/modules/v1/project_packages_spec.rb @@ -103,7 +103,28 @@ RSpec.describe API::Terraform::Modules::V1::ProjectPackages, feature_category: : ) end + shared_examples 'creating a package' do + it 'creates a package' do + expect { api_request } + .to change { project.packages.count }.by(1) + .and change { Packages::PackageFile.count }.by(1) + expect(response).to have_gitlab_http_status(:created) + end + end + + shared_examples 'not creating a package' do |expected_status| + it 'does not create a package' do + expect { api_request } + .to change { project.packages.count }.by(0) + .and change { Packages::PackageFile.count }.by(0) + expect(response).to have_gitlab_http_status(expected_status) + end + end + context 'with valid project' do + let(:user_headers) { { 'PRIVATE-TOKEN' => personal_access_token.token } } + let(:headers) { user_headers.merge(workhorse_headers) } + where(:visibility, :user_role, :member, :token_header, :token_type, :shared_examples_name, :expected_status) do :public | :developer | true | 'PRIVATE-TOKEN' | :personal_access_token | 'process terraform module upload' | :created :public | :guest | true | 'PRIVATE-TOKEN' | :personal_access_token | 'rejects terraform module packages access' | :forbidden @@ -147,7 +168,6 @@ RSpec.describe API::Terraform::Modules::V1::ProjectPackages, feature_category: : with_them do let(:user_headers) { user_role == :anonymous ? {} : { token_header => token } } - let(:headers) { user_headers.merge(workhorse_headers) } let(:snowplow_gitlab_standard_context) do { project: project, namespace: project.namespace, user: snowplow_user, property: 'i_package_terraform_module_user' } @@ -172,43 +192,73 @@ RSpec.describe API::Terraform::Modules::V1::ProjectPackages, feature_category: : end context 'when failed package file save' do - let(:user_headers) { { 'PRIVATE-TOKEN' => personal_access_token.token } } - let(:headers) { user_headers.merge(workhorse_headers) } + before do + project.add_developer(user) + allow(Packages::CreatePackageFileService).to receive(:new).and_raise(StandardError) + end + + it_behaves_like 'not creating a package', :error + end + + context 'with an existing package in the same project' do + let_it_be_with_reload(:existing_package) do + create(:terraform_module_package, name: 'mymodule/mysystem', version: '1.0.0', project: project) + end before do project.add_developer(user) end - it 'does not create package record', :aggregate_failures do - allow(Packages::CreatePackageFileService).to receive(:new).and_raise(StandardError) + it_behaves_like 'not creating a package', :forbidden + + context 'when marked as pending_destruction' do + before do + existing_package.pending_destruction! + end + + it_behaves_like 'creating a package' + end + end + + context 'with existing package in another project' do + let_it_be(:package_settings) { create(:namespace_package_setting, namespace: group) } + let_it_be(:project2) { create(:project, namespace: group) } + let!(:existing_package) { create(:terraform_module_package, name: 'mymodule/mysystem', project: project2) } + + before do + project.add_developer(user) + end + + context 'when duplicates not allowed' do + it_behaves_like 'not creating a package', :forbidden + end + + context 'when duplicates allowed' do + before do + package_settings.update_column(:terraform_module_duplicates_allowed, true) + end - expect { api_request } - .to change { project.packages.count }.by(0) - .and change { Packages::PackageFile.count }.by(0) - expect(response).to have_gitlab_http_status(:error) + it_behaves_like 'creating a package' end - context 'with an existing package' do - let_it_be_with_reload(:existing_package) do - create(:terraform_module_package, name: 'mymodule/mysystem', version: '1.0.0', project: project) + context 'with duplicate regex exception' do + before do + package_settings.update_columns( + terraform_module_duplicates_allowed: false, + terraform_module_duplicate_exception_regex: regex + ) end - it 'does not create a new package' do - expect { api_request } - .to change { project.packages.count }.by(0) - .and change { Packages::PackageFile.count }.by(0) - expect(response).to have_gitlab_http_status(:forbidden) + context 'when regex matches' do + let(:regex) { ".*#{existing_package.name.last(3)}.*" } + + it_behaves_like 'creating a package' end - context 'when marked as pending_destruction' do - it 'does create a new package' do - existing_package.pending_destruction! + context 'when regex does not match' do + let(:regex) { '.*non-matching-regex.*' } - expect { api_request } - .to change { project.packages.count }.by(1) - .and change { Packages::PackageFile.count }.by(1) - expect(response).to have_gitlab_http_status(:created) - end + it_behaves_like 'not creating a package', :forbidden end end end diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb index b2b27a1a075..a6c2b593e40 100644 --- a/spec/services/groups/create_service_spec.rb +++ b/spec/services/groups/create_service_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Groups::CreateService, '#execute', feature_category: :groups_and_ let!(:user) { create(:user) } let!(:group_params) { { path: "group_path", visibility_level: Gitlab::VisibilityLevel::PUBLIC } } - subject { service.execute } + subject(:execute) { service.execute } shared_examples 'has sync-ed traversal_ids' do specify { expect(subject.reload.traversal_ids).to eq([subject.parent&.traversal_ids, subject.id].flatten.compact) } @@ -119,6 +119,49 @@ RSpec.describe Groups::CreateService, '#execute', feature_category: :groups_and_ end end + describe 'creating a group within an organization' do + let(:current_user) { user } + let(:service) { described_class.new(current_user, params) } + + context 'when organization is provided' do + let_it_be(:organization) { create(:organization) } + let(:params) { group_params.merge(organization_id: organization.id) } + + context 'when user can create the group' do + before do + create(:organization_user, user: user, organization: organization) + end + + it { is_expected.to be_persisted } + end + + context 'when user is an admin', :enable_admin_mode do + let(:current_user) { create(:admin) } + + it { is_expected.to be_persisted } + end + + context 'when user can not create the group' do + it 'does not save group and returns an error' do + expect(execute).not_to be_persisted + expect(execute.errors[:organization_id].first) + .to eq(s_("CreateGroup|You don't have permission to create a group in the provided organization.")) + expect(execute.organization_id).to be_nil + end + end + end + + context 'when organization is the default organization and not set by params' do + let(:params) { group_params } + + before do + create(:organization, :default) + end + + it { is_expected.to be_persisted } + end + end + describe 'creating subgroup' do let!(:group) { create(:group) } let!(:service) { described_class.new(user, group_params.merge(parent_id: group.id)) } diff --git a/spec/services/namespaces/package_settings/update_service_spec.rb b/spec/services/namespaces/package_settings/update_service_spec.rb index 41f3499a1bb..002c7df9284 100644 --- a/spec/services/namespaces/package_settings/update_service_spec.rb +++ b/spec/services/namespaces/package_settings/update_service_spec.rb @@ -46,7 +46,9 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService, feature_category: : lock_npm_package_requests_forwarding: false, pypi_package_requests_forwarding: nil, lock_pypi_package_requests_forwarding: false, - nuget_symbol_server_enabled: false + nuget_symbol_server_enabled: false, + terraform_module_duplicates_allowed: false, + terraform_module_duplicate_exception_regex: 'foo' }, to: { maven_duplicates_allowed: false, maven_duplicate_exception_regex: 'RELEASE', @@ -60,7 +62,9 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService, feature_category: : lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, lock_pypi_package_requests_forwarding: true, - nuget_symbol_server_enabled: true + nuget_symbol_server_enabled: true, + terraform_module_duplicates_allowed: true, + terraform_module_duplicate_exception_regex: 'bar' } it_behaves_like 'returning a success' @@ -112,7 +116,9 @@ RSpec.describe ::Namespaces::PackageSettings::UpdateService, feature_category: : lock_npm_package_requests_forwarding: true, pypi_package_requests_forwarding: true, lock_pypi_package_requests_forwarding: true, - nuget_symbol_server_enabled: true + nuget_symbol_server_enabled: true, + terraform_module_duplicates_allowed: true, + terraform_module_duplicate_exception_regex: 'bar' } end diff --git a/spec/services/packages/terraform_module/create_package_service_spec.rb b/spec/services/packages/terraform_module/create_package_service_spec.rb index 3355dfcf5ec..c1a41cd9676 100644 --- a/spec/services/packages/terraform_module/create_package_service_spec.rb +++ b/spec/services/packages/terraform_module/create_package_service_spec.rb @@ -2,10 +2,11 @@ require 'spec_helper' RSpec.describe Packages::TerraformModule::CreatePackageService, feature_category: :package_registry do - let_it_be(:namespace) { create(:namespace) } + let_it_be(:namespace) { create(:group) } let_it_be(:project) { create(:project, namespace: namespace) } let_it_be(:user) { create(:user) } let_it_be(:sha256) { '440e5e148a25331bbd7991575f7d54933c0ebf6cc735a18ee5066ac1381bb590' } + let_it_be(:package_settings) { create(:namespace_package_setting, namespace: namespace) } let(:overrides) { {} } @@ -36,10 +37,72 @@ RSpec.describe Packages::TerraformModule::CreatePackageService, feature_category context 'package already exists elsewhere' do let(:project2) { create(:project, namespace: namespace) } - let!(:existing_package) { create(:terraform_module_package, project: project2, name: 'foo/bar', version: '1.0.0') } + let!(:existing_package) do + create(:terraform_module_package, project: project2, name: 'foo/bar', version: '1.0.0') + end + + context 'when duplicates not allowed' do + it { expect(subject.reason).to eq :forbidden } + it { expect(subject.message).to be 'A package with the same name already exists in the namespace' } + end + + context 'when duplicates allowed' do + before do + package_settings.update_column(:terraform_module_duplicates_allowed, true) + end + + it_behaves_like 'creating a package' + end + + context 'with duplicate regex exception' do + before do + package_settings.update_columns( + terraform_module_duplicates_allowed: false, + terraform_module_duplicate_exception_regex: regex + ) + end + + context 'when regex matches' do + let(:regex) { ".*#{existing_package.name.last(3)}.*" } + + it_behaves_like 'creating a package' + end - it { expect(subject[:http_status]).to eq 403 } - it { expect(subject[:message]).to be 'Access Denied' } + context 'when regex does not match' do + let(:regex) { '.*not-a-match.*' } + + it { expect(subject.reason).to eq :forbidden } + it { expect(subject.message).to be 'A package with the same name already exists in the namespace' } + end + end + + context 'for ancestor namespace' do + let_it_be(:package_settings) { create(:namespace_package_setting, :group) } + let_it_be(:parent_namespace) { package_settings.namespace } + + before do + namespace.update!(parent: parent_namespace) + end + + context 'when duplicates allowed in an ancestor' do + before do + package_settings.update_column(:terraform_module_duplicates_allowed, true) + end + + it_behaves_like 'creating a package' + end + + context 'when duplicates allowed in an ancestor with exception' do + before do + package_settings.update_columns( + terraform_module_duplicates_allowed: false, + terraform_module_duplicate_exception_regex: ".*#{existing_package.name.last(3)}.*" + ) + end + + it_behaves_like 'creating a package' + end + end context 'marked as pending_destruction' do before do @@ -53,7 +116,7 @@ RSpec.describe Packages::TerraformModule::CreatePackageService, feature_category context 'version already exists' do let!(:existing_version) { create(:terraform_module_package, project: project, name: 'foo/bar', version: '1.0.1') } - it { expect(subject[:http_status]).to eq 403 } + it { expect(subject[:reason]).to eq :forbidden } it { expect(subject[:message]).to be 'Package version already exists.' } context 'marked as pending_destruction' do @@ -68,7 +131,7 @@ RSpec.describe Packages::TerraformModule::CreatePackageService, feature_category context 'with empty version' do let(:overrides) { { module_version: '' } } - it { expect(subject[:http_status]).to eq 400 } + it { expect(subject[:reason]).to eq :bad_request } it { expect(subject[:message]).to eq 'Version is empty.' } end end diff --git a/spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb b/spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb index d288c74ae4b..f4bab4d0ad6 100644 --- a/spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb +++ b/spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb @@ -12,6 +12,8 @@ RSpec.shared_examples 'updating the namespace package setting attributes' do |to .and change { namespace.package_settings.reload.nuget_duplicates_allowed }.from(from[:nuget_duplicates_allowed]).to(to[:nuget_duplicates_allowed]) .and change { namespace.package_settings.reload.nuget_duplicate_exception_regex }.from(from[:nuget_duplicate_exception_regex]).to(to[:nuget_duplicate_exception_regex]) .and change { namespace.package_settings.reload.nuget_symbol_server_enabled }.from(from[:nuget_symbol_server_enabled]).to(to[:nuget_symbol_server_enabled]) + .and change { namespace.package_settings.reload.terraform_module_duplicates_allowed }.from(from[:terraform_module_duplicates_allowed]).to(to[:terraform_module_duplicates_allowed]) + .and change { namespace.package_settings.reload.terraform_module_duplicate_exception_regex }.from(from[:terraform_module_duplicate_exception_regex]).to(to[:terraform_module_duplicate_exception_regex]) end end @@ -36,6 +38,8 @@ RSpec.shared_examples 'creating the namespace package setting' do expect(namespace.package_setting_relation.nuget_duplicates_allowed).to eq(package_settings[:nuget_duplicates_allowed]) expect(namespace.package_setting_relation.nuget_duplicate_exception_regex).to eq(package_settings[:nuget_duplicate_exception_regex]) expect(namespace.package_setting_relation.nuget_symbol_server_enabled).to eq(package_settings[:nuget_symbol_server_enabled]) + expect(namespace.package_setting_relation.terraform_module_duplicates_allowed).to eq(package_settings[:terraform_module_duplicates_allowed]) + expect(namespace.package_setting_relation.terraform_module_duplicate_exception_regex).to eq(package_settings[:terraform_module_duplicate_exception_regex]) end it_behaves_like 'returning a success' |